blob: e267de8c8330037d7b06d913a150ee3fe9367f46 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
Simon Horman66183002013-02-23 10:16:43 +09001325 defproxy.defsrv.check.inter = DEF_CHKINTR;
1326 defproxy.defsrv.check.fastinter = 0;
1327 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001328 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1329 defproxy.defsrv.agent.fastinter = 0;
1330 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001331 defproxy.defsrv.check.rise = DEF_RISETIME;
1332 defproxy.defsrv.check.fall = DEF_FALLTIME;
1333 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1334 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001335 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001336 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001337 defproxy.defsrv.maxqueue = 0;
1338 defproxy.defsrv.minconn = 0;
1339 defproxy.defsrv.maxconn = 0;
1340 defproxy.defsrv.slowstart = 0;
1341 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1342 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1343 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344}
1345
Willy Tarreauade5ec42010-01-28 19:33:49 +01001346
1347static int create_cond_regex_rule(const char *file, int line,
1348 struct proxy *px, int dir, int action, int flags,
1349 const char *cmd, const char *reg, const char *repl,
1350 const char **cond_start)
1351{
1352 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001353 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001354 const char *err;
1355 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001356 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001357
1358 if (px == &defproxy) {
1359 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (*reg == 0) {
1365 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto err;
1368 }
1369
1370 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1371 err_code |= ERR_WARN;
1372
Willy Tarreau5321c422010-01-28 20:35:13 +01001373 if (cond_start &&
1374 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001375 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1376 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1377 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto err;
1380 }
1381 }
1382 else if (cond_start && **cond_start) {
1383 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1384 file, line, cmd, *cond_start);
1385 err_code |= ERR_ALERT | ERR_FATAL;
1386 goto err;
1387 }
1388
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001389 err_code |= warnif_cond_conflicts(cond,
1390 (dir == SMP_OPT_DIR_REQ) ?
1391 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1392 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1393 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001394
Willy Tarreauade5ec42010-01-28 19:33:49 +01001395 preg = calloc(1, sizeof(regex_t));
1396 if (!preg) {
1397 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
1402 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1403 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1404 err_code = ERR_ALERT | ERR_FATAL;
1405 goto err;
1406 }
1407
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001408 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001409 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001410 if (repl && err) {
1411 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1412 file, line, cmd, *err);
1413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto err;
1415 }
1416
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001417 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 err_code |= ERR_WARN;
1419
Willy Tarreauf4068b62012-05-08 17:37:49 +02001420 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001421 return err_code;
1422 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001423 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001424 free(preg);
1425 return err_code;
1426}
1427
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001429 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001430 * Returns the error code, 0 if OK, or any combination of :
1431 * - ERR_ABORT: must abort ASAP
1432 * - ERR_FATAL: we can continue parsing but not start the service
1433 * - ERR_WARN: a warning has been emitted
1434 * - ERR_ALERT: an alert has been emitted
1435 * Only the two first ones can stop processing, the two others are just
1436 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001438int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1439{
1440 static struct peers *curpeers = NULL;
1441 struct peer *newpeer = NULL;
1442 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001443 struct bind_conf *bind_conf;
1444 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001445 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001446 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001447
1448 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001449 if (!*args[1]) {
1450 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
1453 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001454
1455 err = invalid_char(args[1]);
1456 if (err) {
1457 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1458 file, linenum, *err, args[0], args[1]);
1459 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001460 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001461 }
1462
1463 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1464 /*
1465 * If there are two proxies with the same name only following
1466 * combinations are allowed:
1467 */
1468 if (strcmp(curpeers->id, args[1]) == 0) {
1469 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1470 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1471 err_code |= ERR_WARN;
1472 }
1473 }
1474
1475 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1477 err_code |= ERR_ALERT | ERR_ABORT;
1478 goto out;
1479 }
1480
1481 curpeers->next = peers;
1482 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001483 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001484 curpeers->conf.line = linenum;
1485 curpeers->last_change = now.tv_sec;
1486 curpeers->id = strdup(args[1]);
1487 }
1488 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001489 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001490 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001491 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001492
1493 if (!*args[2]) {
1494 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1495 file, linenum, args[0]);
1496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
1498 }
1499
1500 err = invalid_char(args[1]);
1501 if (err) {
1502 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1503 file, linenum, *err, args[1]);
1504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
1506 }
1507
1508 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1509 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1510 err_code |= ERR_ALERT | ERR_ABORT;
1511 goto out;
1512 }
1513
1514 /* the peers are linked backwards first */
1515 curpeers->count++;
1516 newpeer->next = curpeers->remote;
1517 curpeers->remote = newpeer;
1518 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001519 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001520 newpeer->conf.line = linenum;
1521
1522 newpeer->last_change = now.tv_sec;
1523 newpeer->id = strdup(args[1]);
1524
Willy Tarreau902636f2013-03-10 19:44:48 +01001525 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001526 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001527 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001530 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001531
1532 proto = protocol_by_family(sk->ss_family);
1533 if (!proto || !proto->connect) {
1534 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1535 file, linenum, args[0], args[1]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001539
1540 if (port1 != port2) {
1541 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1542 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
1546
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547 if (!port1) {
1548 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1549 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
1552 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001553
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001555 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001556 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001557 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001558
Emeric Brun32da3c42010-09-23 18:39:19 +02001559 if (strcmp(newpeer->id, localpeer) == 0) {
1560 /* Current is local peer, it define a frontend */
1561 newpeer->local = 1;
1562
1563 if (!curpeers->peers_fe) {
1564 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1565 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1566 err_code |= ERR_ALERT | ERR_ABORT;
1567 goto out;
1568 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001569
Willy Tarreau237250c2011-07-29 01:49:03 +02001570 init_new_proxy(curpeers->peers_fe);
1571 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001572
1573 curpeers->peers_fe->last_change = now.tv_sec;
1574 curpeers->peers_fe->id = strdup(args[1]);
1575 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001576 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001577 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1578 curpeers->peers_fe->timeout.connect = 5000;
1579 curpeers->peers_fe->accept = peer_accept;
1580 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001581 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1582 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001583
1584 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1585
Willy Tarreau902636f2013-03-10 19:44:48 +01001586 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1587 if (errmsg && *errmsg) {
1588 indent_msg(&errmsg, 2);
1589 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001590 }
1591 else
1592 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1593 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001594 err_code |= ERR_FATAL;
1595 goto out;
1596 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001597
1598 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1599 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1600 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1601 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1602 l->accept = session_accept;
1603 l->handler = process_session;
1604 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1605 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1606 global.maxsock += l->maxconn;
1607 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001608 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001609 else {
1610 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1611 file, linenum, args[0], args[1],
1612 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1613 err_code |= ERR_FATAL;
1614 goto out;
1615 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001616 }
1617 } /* neither "peer" nor "peers" */
1618 else if (*args[0] != 0) {
1619 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623
1624out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001625 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001626 return err_code;
1627}
1628
Simon Horman69d29f92013-02-23 15:14:19 +09001629static int init_check(struct check *check, int type, const char * file, int linenum)
1630{
1631 check->type = type;
1632
1633 /* Allocate buffer for requests... */
1634 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1635 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1636 return ERR_ALERT | ERR_ABORT;
1637 }
1638 check->bi->size = global.tune.chksize;
1639
1640 /* Allocate buffer for responses... */
1641 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1642 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1643 return ERR_ALERT | ERR_ABORT;
1644 }
1645 check->bo->size = global.tune.chksize;
1646
1647 /* Allocate buffer for partial results... */
1648 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1649 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1650 return ERR_ALERT | ERR_ABORT;
1651 }
1652
1653 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1654
1655 return 0;
1656}
Emeric Brun32da3c42010-09-23 18:39:19 +02001657
Willy Tarreau3842f002009-06-14 11:39:52 +02001658int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659{
1660 static struct proxy *curproxy = NULL;
1661 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001662 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001663 int rc;
1664 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001665 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001666 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001667 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001668 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001669 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670
Willy Tarreau977b8e42006-12-29 14:19:17 +01001671 if (!strcmp(args[0], "listen"))
1672 rc = PR_CAP_LISTEN;
1673 else if (!strcmp(args[0], "frontend"))
1674 rc = PR_CAP_FE | PR_CAP_RS;
1675 else if (!strcmp(args[0], "backend"))
1676 rc = PR_CAP_BE | PR_CAP_RS;
1677 else if (!strcmp(args[0], "ruleset"))
1678 rc = PR_CAP_RS;
1679 else
1680 rc = PR_CAP_NONE;
1681
1682 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 if (!*args[1]) {
1684 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1685 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_ABORT;
1688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001690
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001691 err = invalid_char(args[1]);
1692 if (err) {
1693 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1694 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001696 }
1697
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001698 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1699 /*
1700 * If there are two proxies with the same name only following
1701 * combinations are allowed:
1702 *
1703 * listen backend frontend ruleset
1704 * listen - - - -
1705 * backend - - OK -
1706 * frontend - OK - -
1707 * ruleset - - - -
1708 */
1709
1710 if (!strcmp(curproxy->id, args[1]) &&
1711 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1712 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001713 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1714 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1715 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001717 }
1718 }
1719
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1721 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_ABORT;
1723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001725
Willy Tarreau97cb7802010-01-03 20:23:58 +01001726 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 curproxy->next = proxy;
1728 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001729 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1730 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001731 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001733 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734
1735 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001736 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001737 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001738
Willy Tarreau4348fad2012-09-20 16:48:07 +02001739 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1740
Willy Tarreau902636f2013-03-10 19:44:48 +01001741 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1742 if (errmsg && *errmsg) {
1743 indent_msg(&errmsg, 2);
1744 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001745 }
1746 else
1747 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1748 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_FATAL;
1750 goto out;
1751 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001752
Willy Tarreau4348fad2012-09-20 16:48:07 +02001753 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001754 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 }
1757
1758 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001759 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001760 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001761
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001764 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001765 curproxy->no_options = defproxy.no_options;
1766 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001767 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001768 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001769 curproxy->except_net = defproxy.except_net;
1770 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001771 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001772 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001774 if (defproxy.fwdfor_hdr_len) {
1775 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1776 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1777 }
1778
Willy Tarreaub86db342009-11-30 11:50:16 +01001779 if (defproxy.orgto_hdr_len) {
1780 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1781 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1782 }
1783
Mark Lamourinec2247f02012-01-04 13:02:01 -05001784 if (defproxy.server_id_hdr_len) {
1785 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1786 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1787 }
1788
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 if (curproxy->cap & PR_CAP_FE) {
1790 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001791 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001792 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793
1794 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001795 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1796 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001797
1798 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (curproxy->cap & PR_CAP_BE) {
1802 curproxy->fullconn = defproxy.fullconn;
1803 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001805 if (defproxy.check_req) {
1806 curproxy->check_req = calloc(1, defproxy.check_len);
1807 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1808 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001809 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001811 if (defproxy.expect_str) {
1812 curproxy->expect_str = strdup(defproxy.expect_str);
1813 if (defproxy.expect_regex) {
1814 /* note: this regex is known to be valid */
1815 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1816 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1817 }
1818 }
1819
Willy Tarreau67402132012-05-31 20:40:20 +02001820 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001821 if (defproxy.cookie_name)
1822 curproxy->cookie_name = strdup(defproxy.cookie_name);
1823 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001824 if (defproxy.cookie_domain)
1825 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001826
Willy Tarreau31936852010-10-06 16:59:56 +02001827 if (defproxy.cookie_maxidle)
1828 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1829
1830 if (defproxy.cookie_maxlife)
1831 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1832
Emeric Brun647caf12009-06-30 17:57:00 +02001833 if (defproxy.rdp_cookie_name)
1834 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1835 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1836
Willy Tarreau01732802007-11-01 22:48:15 +01001837 if (defproxy.url_param_name)
1838 curproxy->url_param_name = strdup(defproxy.url_param_name);
1839 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001840
Benoitaffb4812009-03-25 13:02:10 +01001841 if (defproxy.hh_name)
1842 curproxy->hh_name = strdup(defproxy.hh_name);
1843 curproxy->hh_len = defproxy.hh_len;
1844 curproxy->hh_match_domain = defproxy.hh_match_domain;
1845
Willy Tarreauef9a3602012-12-08 22:29:20 +01001846 if (defproxy.conn_src.iface_name)
1847 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1848 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001849 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001850#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001851 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001852#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001855 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001856 if (defproxy.capture_name)
1857 curproxy->capture_name = strdup(defproxy.capture_name);
1858 curproxy->capture_namelen = defproxy.capture_namelen;
1859 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861
Willy Tarreau977b8e42006-12-29 14:19:17 +01001862 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001863 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001864 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001865 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001866 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001867 curproxy->uri_auth = defproxy.uri_auth;
1868 curproxy->mon_net = defproxy.mon_net;
1869 curproxy->mon_mask = defproxy.mon_mask;
1870 if (defproxy.monitor_uri)
1871 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1872 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001873 if (defproxy.defbe.name)
1874 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001875
1876 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001877 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1878 if (curproxy->conf.logformat_string &&
1879 curproxy->conf.logformat_string != default_http_log_format &&
1880 curproxy->conf.logformat_string != default_tcp_log_format &&
1881 curproxy->conf.logformat_string != clf_http_log_format)
1882 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1883
1884 if (defproxy.conf.lfs_file) {
1885 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1886 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1887 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001888 }
1889
1890 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001891 curproxy->timeout.connect = defproxy.timeout.connect;
1892 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001893 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001894 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001895 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001896 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001897 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001898 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001899 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900 }
1901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001903
1904 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001905 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001906 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001907 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001908 LIST_INIT(&node->list);
1909 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1910 }
1911
Willy Tarreau62a61232013-04-12 18:13:46 +02001912 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1913 if (curproxy->conf.uniqueid_format_string)
1914 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1915
1916 if (defproxy.conf.uif_file) {
1917 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1918 curproxy->conf.uif_line = defproxy.conf.uif_line;
1919 }
William Lallemanda73203e2012-03-12 12:48:57 +01001920
1921 /* copy default header unique id */
1922 if (defproxy.header_unique_id)
1923 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1924
William Lallemand82fe75c2012-10-23 10:25:10 +02001925 /* default compression options */
1926 if (defproxy.comp != NULL) {
1927 curproxy->comp = calloc(1, sizeof(struct comp));
1928 curproxy->comp->algos = defproxy.comp->algos;
1929 curproxy->comp->types = defproxy.comp->types;
1930 }
1931
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001933 curproxy->conf.used_listener_id = EB_ROOT;
1934 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001935
Willy Tarreau93893792009-07-23 13:19:11 +02001936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
1938 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1939 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001940 /* FIXME-20070101: we should do this too at the end of the
1941 * config parsing to free all default values.
1942 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001943 free(defproxy.check_req);
1944 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001945 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001946 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001947 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001948 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001949 free(defproxy.capture_name);
1950 free(defproxy.monitor_uri);
1951 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001952 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001953 free(defproxy.fwdfor_hdr_name);
1954 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001955 free(defproxy.orgto_hdr_name);
1956 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001957 free(defproxy.server_id_hdr_name);
1958 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001959 free(defproxy.expect_str);
1960 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001961
Willy Tarreau62a61232013-04-12 18:13:46 +02001962 if (defproxy.conf.logformat_string != default_http_log_format &&
1963 defproxy.conf.logformat_string != default_tcp_log_format &&
1964 defproxy.conf.logformat_string != clf_http_log_format)
1965 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001966
Willy Tarreau62a61232013-04-12 18:13:46 +02001967 free(defproxy.conf.uniqueid_format_string);
1968 free(defproxy.conf.lfs_file);
1969 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001970
Willy Tarreaua534fea2008-08-03 12:19:50 +02001971 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001972 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001973
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974 /* we cannot free uri_auth because it might already be used */
1975 init_default_instance();
1976 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001977 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1978 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 }
1982 else if (curproxy == NULL) {
1983 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001987
1988 /* update the current file and line being parsed */
1989 curproxy->conf.args.file = curproxy->conf.file;
1990 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001991
1992 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001995 int cur_arg;
1996
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 if (curproxy == &defproxy) {
1998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004
Willy Tarreau24709282013-03-10 21:32:12 +01002005 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002006 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002011
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002012 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002013
2014 /* use default settings for unix sockets */
2015 bind_conf->ux.uid = global.unix_bind.ux.uid;
2016 bind_conf->ux.gid = global.unix_bind.ux.gid;
2017 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002018
2019 /* NOTE: the following line might create several listeners if there
2020 * are comma-separated IPs or port ranges. So all further processing
2021 * will have to be applied to all listeners created after last_listen.
2022 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002023 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2024 if (errmsg && *errmsg) {
2025 indent_msg(&errmsg, 2);
2026 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002027 }
2028 else
2029 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2030 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002034
Willy Tarreau4348fad2012-09-20 16:48:07 +02002035 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2036 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002037 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002038 }
2039
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002040 cur_arg = 2;
2041 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002042 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002043 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002044 char *err;
2045
Willy Tarreau26982662012-09-12 23:17:10 +02002046 kw = bind_find_kw(args[cur_arg]);
2047 if (kw) {
2048 char *err = NULL;
2049 int code;
2050
2051 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002052 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2053 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002054 cur_arg += 1 + kw->skip ;
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058
Willy Tarreau4348fad2012-09-20 16:48:07 +02002059 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002060 err_code |= code;
2061
2062 if (code) {
2063 if (err && *err) {
2064 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002065 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002066 }
2067 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002068 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2069 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002070 if (code & ERR_FATAL) {
2071 free(err);
2072 cur_arg += 1 + kw->skip;
2073 goto out;
2074 }
2075 }
2076 free(err);
2077 cur_arg += 1 + kw->skip;
2078 continue;
2079 }
2080
Willy Tarreau8638f482012-09-18 18:01:17 +02002081 err = NULL;
2082 if (!bind_dumped) {
2083 bind_dump_kws(&err);
2084 indent_msg(&err, 4);
2085 bind_dumped = 1;
2086 }
2087
2088 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2089 file, linenum, args[0], args[1], args[cur_arg],
2090 err ? " Registered keywords :" : "", err ? err : "");
2091 free(err);
2092
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002095 }
Willy Tarreau93893792009-07-23 13:19:11 +02002096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 }
2098 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2099 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2100 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108 /* flush useless bits */
2109 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002112 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002113 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115
Willy Tarreau1c47f852006-07-09 08:22:27 +02002116 if (!*args[1]) {
2117 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2118 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002121 }
2122
Willy Tarreaua534fea2008-08-03 12:19:50 +02002123 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002124 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002125 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002126 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002127 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2128
Willy Tarreau93893792009-07-23 13:19:11 +02002129 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2132 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2133 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2134 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2135 else {
2136 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 }
2140 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002141 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002142 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002143
2144 if (curproxy == &defproxy) {
2145 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2146 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002149 }
2150
2151 if (!*args[1]) {
2152 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002156 }
2157
2158 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002159 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002160
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002161 if (curproxy->uuid <= 0) {
2162 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002163 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002166 }
2167
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002168 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2169 if (node) {
2170 struct proxy *target = container_of(node, struct proxy, conf.id);
2171 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2172 file, linenum, proxy_type_str(curproxy), curproxy->id,
2173 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
2177 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002178 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002179 else if (!strcmp(args[0], "description")) {
2180 int i, len=0;
2181 char *d;
2182
Cyril Bonté99ed3272010-01-24 23:29:44 +01002183 if (curproxy == &defproxy) {
2184 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2185 file, linenum, args[0]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002190 if (!*args[1]) {
2191 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2192 file, linenum, args[0]);
2193 return -1;
2194 }
2195
2196 for(i=1; *args[i]; i++)
2197 len += strlen(args[i])+1;
2198
2199 d = (char *)calloc(1, len);
2200 curproxy->desc = d;
2201
2202 d += sprintf(d, "%s", args[1]);
2203 for(i=2; *args[i]; i++)
2204 d += sprintf(d, " %s", args[i]);
2205
2206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2208 curproxy->state = PR_STSTOPPED;
2209 }
2210 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2211 curproxy->state = PR_STNEW;
2212 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002213 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2214 int cur_arg = 1;
2215 unsigned int set = 0;
2216
2217 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002218 unsigned int low, high;
2219
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002220 if (strcmp(args[cur_arg], "all") == 0) {
2221 set = 0;
2222 break;
2223 }
2224 else if (strcmp(args[cur_arg], "odd") == 0) {
2225 set |= 0x55555555;
2226 }
2227 else if (strcmp(args[cur_arg], "even") == 0) {
2228 set |= 0xAAAAAAAA;
2229 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002230 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002231 char *dash = strchr(args[cur_arg], '-');
2232
2233 low = high = str2uic(args[cur_arg]);
2234 if (dash)
2235 high = str2uic(dash + 1);
2236
2237 if (high < low) {
2238 unsigned int swap = low;
2239 low = high;
2240 high = swap;
2241 }
2242
2243 if (low < 1 || high > 32) {
2244 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002248 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002249
2250 if (high > global.nbproc) {
2251 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2252 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002254 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002255 while (low <= high)
2256 set |= 1 << (low++ - 1);
2257 }
2258 else {
2259 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2260 file, linenum, args[0]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002263 }
2264 cur_arg++;
2265 }
2266 curproxy->bind_proc = set;
2267 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002268 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002269 if (curproxy == &defproxy) {
2270 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002273 }
2274
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002275 err = invalid_char(args[1]);
2276 if (err) {
2277 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2278 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002280 }
2281
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002282 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002283 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2284 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002287 }
2288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2290 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291
Willy Tarreau977b8e42006-12-29 14:19:17 +01002292 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 if (*(args[1]) == 0) {
2296 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002301
Willy Tarreau67402132012-05-31 20:40:20 +02002302 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002303 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002304 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->cookie_name = strdup(args[1]);
2307 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002308
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 cur_arg = 2;
2310 while (*(args[cur_arg])) {
2311 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002312 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
2314 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002315 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
2317 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002318 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
2320 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002321 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
2323 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002324 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002326 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002327 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002330 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002332 else if (!strcmp(args[cur_arg], "httponly")) {
2333 curproxy->ck_opts |= PR_CK_HTTPONLY;
2334 }
2335 else if (!strcmp(args[cur_arg], "secure")) {
2336 curproxy->ck_opts |= PR_CK_SECURE;
2337 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002338 else if (!strcmp(args[cur_arg], "domain")) {
2339 if (!*args[cur_arg + 1]) {
2340 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2341 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002344 }
2345
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002346 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002347 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002348 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2349 " dots nor does not start with a dot."
2350 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002351 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002352 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002353 }
2354
2355 err = invalid_domainchar(args[cur_arg + 1]);
2356 if (err) {
2357 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2358 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002361 }
2362
Willy Tarreau68a897b2009-12-03 23:28:34 +01002363 if (!curproxy->cookie_domain) {
2364 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2365 } else {
2366 /* one domain was already specified, add another one by
2367 * building the string which will be returned along with
2368 * the cookie.
2369 */
2370 char *new_ptr;
2371 int new_len = strlen(curproxy->cookie_domain) +
2372 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2373 new_ptr = malloc(new_len);
2374 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2375 free(curproxy->cookie_domain);
2376 curproxy->cookie_domain = new_ptr;
2377 }
Willy Tarreau31936852010-10-06 16:59:56 +02002378 cur_arg++;
2379 }
2380 else if (!strcmp(args[cur_arg], "maxidle")) {
2381 unsigned int maxidle;
2382 const char *res;
2383
2384 if (!*args[cur_arg + 1]) {
2385 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2386 file, linenum, args[cur_arg]);
2387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
2389 }
2390
2391 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2392 if (res) {
2393 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2394 file, linenum, *res, args[cur_arg]);
2395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
2397 }
2398 curproxy->cookie_maxidle = maxidle;
2399 cur_arg++;
2400 }
2401 else if (!strcmp(args[cur_arg], "maxlife")) {
2402 unsigned int maxlife;
2403 const char *res;
2404
2405 if (!*args[cur_arg + 1]) {
2406 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2407 file, linenum, args[cur_arg]);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
2412 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2413 if (res) {
2414 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2415 file, linenum, *res, args[cur_arg]);
2416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
2418 }
2419 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002420 cur_arg++;
2421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002423 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
2428 cur_arg++;
2429 }
Willy Tarreau67402132012-05-31 20:40:20 +02002430 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435
Willy Tarreau67402132012-05-31 20:40:20 +02002436 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2438 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002441
Willy Tarreau67402132012-05-31 20:40:20 +02002442 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002443 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2444 file, linenum);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002448 else if (!strcmp(args[0], "persist")) { /* persist */
2449 if (*(args[1]) == 0) {
2450 Alert("parsing [%s:%d] : missing persist method.\n",
2451 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002454 }
2455
2456 if (!strncmp(args[1], "rdp-cookie", 10)) {
2457 curproxy->options2 |= PR_O2_RDPC_PRST;
2458
Emeric Brunb982a3d2010-01-04 15:45:53 +01002459 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002460 const char *beg, *end;
2461
2462 beg = args[1] + 11;
2463 end = strchr(beg, ')');
2464
2465 if (!end || end == beg) {
2466 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2467 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002470 }
2471
2472 free(curproxy->rdp_cookie_name);
2473 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2474 curproxy->rdp_cookie_len = end-beg;
2475 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002476 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002477 free(curproxy->rdp_cookie_name);
2478 curproxy->rdp_cookie_name = strdup("msts");
2479 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2480 }
2481 else { /* syntax */
2482 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2483 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002486 }
2487 }
2488 else {
2489 Alert("parsing [%s:%d] : unknown persist method.\n",
2490 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002493 }
2494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002496 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002498 if (curproxy == &defproxy) {
2499 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
Willy Tarreau977b8e42006-12-29 14:19:17 +01002504 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002508 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002514 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 curproxy->appsession_name = strdup(args[1]);
2516 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2517 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002518 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2519 if (err) {
2520 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2521 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002524 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002525 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002526
Willy Tarreau51041c72007-09-09 21:56:53 +02002527 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2528 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_ABORT;
2530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002532
2533 cur_arg = 6;
2534 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002535 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2536 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002537 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002538 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002539 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002540 } else if (!strcmp(args[cur_arg], "prefix")) {
2541 curproxy->options2 |= PR_O2_AS_PFX;
2542 } else if (!strcmp(args[cur_arg], "mode")) {
2543 if (!*args[cur_arg + 1]) {
2544 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2545 file, linenum, args[0], args[cur_arg]);
2546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
2548 }
2549
2550 cur_arg++;
2551 if (!strcmp(args[cur_arg], "query-string")) {
2552 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2553 curproxy->options2 |= PR_O2_AS_M_QS;
2554 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2555 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2556 curproxy->options2 |= PR_O2_AS_M_PP;
2557 } else {
2558 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002563 cur_arg++;
2564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 } /* Url App Session */
2566 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002567 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002571 if (curproxy == &defproxy) {
2572 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
2575 }
2576
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 if (*(args[4]) == 0) {
2578 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2579 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002583 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 curproxy->capture_name = strdup(args[2]);
2585 curproxy->capture_namelen = strlen(curproxy->capture_name);
2586 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 curproxy->to_log |= LW_COOKIE;
2588 }
2589 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2590 struct cap_hdr *hdr;
2591
2592 if (curproxy == &defproxy) {
2593 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597
2598 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2599 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2600 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 }
2604
2605 hdr = calloc(sizeof(struct cap_hdr), 1);
2606 hdr->next = curproxy->req_cap;
2607 hdr->name = strdup(args[3]);
2608 hdr->namelen = strlen(args[3]);
2609 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002610 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 hdr->index = curproxy->nb_req_cap++;
2612 curproxy->req_cap = hdr;
2613 curproxy->to_log |= LW_REQHDR;
2614 }
2615 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2616 struct cap_hdr *hdr;
2617
2618 if (curproxy == &defproxy) {
2619 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623
2624 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2625 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2626 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 }
2630 hdr = calloc(sizeof(struct cap_hdr), 1);
2631 hdr->next = curproxy->rsp_cap;
2632 hdr->name = strdup(args[3]);
2633 hdr->namelen = strlen(args[3]);
2634 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002635 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 hdr->index = curproxy->nb_rsp_cap++;
2637 curproxy->rsp_cap = hdr;
2638 curproxy->to_log |= LW_RSPHDR;
2639 }
2640 else {
2641 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }
2646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 if (*(args[1]) == 0) {
2652 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 }
2657 curproxy->conn_retries = atol(args[1]);
2658 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002659 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002660 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002661
2662 if (curproxy == &defproxy) {
2663 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
Willy Tarreau20b0de52012-12-24 15:45:22 +01002668 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2669 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2670 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2671 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002672 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002673 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2674 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002675 file, linenum, args[0]);
2676 err_code |= ERR_WARN;
2677 }
2678
Willy Tarreauff011f22011-01-06 17:51:27 +01002679 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002680
Willy Tarreauff011f22011-01-06 17:51:27 +01002681 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002682 err_code |= ERR_ALERT | ERR_ABORT;
2683 goto out;
2684 }
2685
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002686 err_code |= warnif_cond_conflicts(rule->cond,
2687 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2688 file, linenum);
2689
Willy Tarreauff011f22011-01-06 17:51:27 +01002690 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002691 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002692 else if (!strcmp(args[0], "http-response")) { /* response access control */
2693 struct http_res_rule *rule;
2694
2695 if (curproxy == &defproxy) {
2696 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
2701 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2702 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2703 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2704 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2705 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2706 file, linenum, args[0]);
2707 err_code |= ERR_WARN;
2708 }
2709
2710 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2711
2712 if (!rule) {
2713 err_code |= ERR_ALERT | ERR_ABORT;
2714 goto out;
2715 }
2716
2717 err_code |= warnif_cond_conflicts(rule->cond,
2718 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2719 file, linenum);
2720
2721 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2722 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002723 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2724 /* set the header name and length into the proxy structure */
2725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2726 err_code |= ERR_WARN;
2727
2728 if (!*args[1]) {
2729 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2730 file, linenum, args[0]);
2731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
2733 }
2734
2735 /* set the desired header name */
2736 free(curproxy->server_id_hdr_name);
2737 curproxy->server_id_hdr_name = strdup(args[1]);
2738 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2739 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002740 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002741 if (curproxy == &defproxy) {
2742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002745 }
2746
Willy Tarreauef6494c2010-01-28 17:12:36 +01002747 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002748 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2749 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002752 }
2753
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002754 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2755 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2756 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002759 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002760
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002761 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002762 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002763 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002764 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002765 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002766
Cyril Bonté99ed3272010-01-24 23:29:44 +01002767 if (curproxy == &defproxy) {
2768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002773 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002774 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2775 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002778 }
2779
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002780 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002781 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002782 err_code |= warnif_cond_conflicts(rule->cond,
2783 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2784 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002785 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002786 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002787 struct switching_rule *rule;
2788
Willy Tarreaub099aca2008-10-12 17:26:37 +02002789 if (curproxy == &defproxy) {
2790 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002793 }
2794
Willy Tarreau55ea7572007-06-17 19:56:27 +02002795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002796 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002797
2798 if (*(args[1]) == 0) {
2799 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002802 }
2803
Willy Tarreauef6494c2010-01-28 17:12:36 +01002804 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002805 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2806 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002809 }
2810
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002811 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2812 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2813 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002816 }
2817
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002818 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002819
Willy Tarreau55ea7572007-06-17 19:56:27 +02002820 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2821 rule->cond = cond;
2822 rule->be.name = strdup(args[1]);
2823 LIST_INIT(&rule->list);
2824 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2825 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002826 else if (strcmp(args[0], "use-server") == 0) {
2827 struct server_rule *rule;
2828
2829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
2835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2836 err_code |= ERR_WARN;
2837
2838 if (*(args[1]) == 0) {
2839 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843
2844 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2845 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2846 file, linenum, args[0]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
2850
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002851 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2852 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2853 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
2856 }
2857
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002858 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002859
2860 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2861 rule->cond = cond;
2862 rule->srv.name = strdup(args[1]);
2863 LIST_INIT(&rule->list);
2864 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2865 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2866 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002867 else if ((!strcmp(args[0], "force-persist")) ||
2868 (!strcmp(args[0], "ignore-persist"))) {
2869 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002870
2871 if (curproxy == &defproxy) {
2872 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2878 err_code |= ERR_WARN;
2879
Willy Tarreauef6494c2010-01-28 17:12:36 +01002880 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002881 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2882 file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002887 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2888 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2889 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002894 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2895 * where force-persist is applied.
2896 */
2897 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002898
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002899 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002900 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002901 if (!strcmp(args[0], "force-persist")) {
2902 rule->type = PERSIST_TYPE_FORCE;
2903 } else {
2904 rule->type = PERSIST_TYPE_IGNORE;
2905 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002906 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002907 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002908 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002909 else if (!strcmp(args[0], "stick-table")) {
2910 int myidx = 1;
2911
Emeric Brun32da3c42010-09-23 18:39:19 +02002912 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002913 curproxy->table.type = (unsigned int)-1;
2914 while (*args[myidx]) {
2915 const char *err;
2916
2917 if (strcmp(args[myidx], "size") == 0) {
2918 myidx++;
2919 if (!*(args[myidx])) {
2920 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2921 file, linenum, args[myidx-1]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2926 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2927 file, linenum, *err, args[myidx-1]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002931 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002932 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002933 else if (strcmp(args[myidx], "peers") == 0) {
2934 myidx++;
2935 if (!*(args[myidx])) {
2936 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2937 file, linenum, args[myidx-1]);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940 }
2941 curproxy->table.peers.name = strdup(args[myidx++]);
2942 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 else if (strcmp(args[myidx], "expire") == 0) {
2944 myidx++;
2945 if (!*(args[myidx])) {
2946 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2947 file, linenum, args[myidx-1]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2952 if (err) {
2953 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2954 file, linenum, *err, args[myidx-1]);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002959 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 }
2961 else if (strcmp(args[myidx], "nopurge") == 0) {
2962 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002963 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002964 }
2965 else if (strcmp(args[myidx], "type") == 0) {
2966 myidx++;
2967 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2968 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2969 file, linenum, args[myidx]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002973 /* myidx already points to next arg */
2974 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002975 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002976 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002977 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002978
2979 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002980 nw = args[myidx];
2981 while (*nw) {
2982 /* the "store" keyword supports a comma-separated list */
2983 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002984 sa = NULL; /* store arg */
2985 while (*nw && *nw != ',') {
2986 if (*nw == '(') {
2987 *nw = 0;
2988 sa = ++nw;
2989 while (*nw != ')') {
2990 if (!*nw) {
2991 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2992 file, linenum, args[0], cw);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996 nw++;
2997 }
2998 *nw = '\0';
2999 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003000 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003001 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003002 if (*nw)
3003 *nw++ = '\0';
3004 type = stktable_get_data_type(cw);
3005 if (type < 0) {
3006 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3007 file, linenum, args[0], cw);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
Willy Tarreauac782882010-06-20 10:41:54 +02003011
3012 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3013 switch (err) {
3014 case PE_NONE: break;
3015 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003016 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3017 file, linenum, args[0], cw);
3018 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003019 break;
3020
3021 case PE_ARG_MISSING:
3022 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3023 file, linenum, args[0], cw);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026
3027 case PE_ARG_NOT_USED:
3028 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3029 file, linenum, args[0], cw);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032
3033 default:
3034 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3035 file, linenum, args[0], cw);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003038 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003039 }
3040 myidx++;
3041 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003042 else {
3043 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3044 file, linenum, args[myidx]);
3045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 }
3049
3050 if (!curproxy->table.size) {
3051 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3052 file, linenum);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056
3057 if (curproxy->table.type == (unsigned int)-1) {
3058 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3059 file, linenum);
3060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063 }
3064 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003065 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003066 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003067 int myidx = 0;
3068 const char *name = NULL;
3069 int flags;
3070
3071 if (curproxy == &defproxy) {
3072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
3075 }
3076
3077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3078 err_code |= ERR_WARN;
3079 goto out;
3080 }
3081
3082 myidx++;
3083 if ((strcmp(args[myidx], "store") == 0) ||
3084 (strcmp(args[myidx], "store-request") == 0)) {
3085 myidx++;
3086 flags = STK_IS_STORE;
3087 }
3088 else if (strcmp(args[myidx], "store-response") == 0) {
3089 myidx++;
3090 flags = STK_IS_STORE | STK_ON_RSP;
3091 }
3092 else if (strcmp(args[myidx], "match") == 0) {
3093 myidx++;
3094 flags = STK_IS_MATCH;
3095 }
3096 else if (strcmp(args[myidx], "on") == 0) {
3097 myidx++;
3098 flags = STK_IS_MATCH | STK_IS_STORE;
3099 }
3100 else {
3101 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105
3106 if (*(args[myidx]) == 0) {
3107 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003112 curproxy->conf.args.ctx = ARGC_STK;
3113 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003114 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003115 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
3120 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003121 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3122 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3123 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003124 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003125 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 goto out;
3127 }
3128 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003129 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3130 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3131 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003132 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003133 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003134 goto out;
3135 }
3136 }
3137
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003138 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003139 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003140
Emeric Brunb982a3d2010-01-04 15:45:53 +01003141 if (strcmp(args[myidx], "table") == 0) {
3142 myidx++;
3143 name = args[myidx++];
3144 }
3145
Willy Tarreauef6494c2010-01-28 17:12:36 +01003146 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003147 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3148 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3149 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003150 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003151 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003152 goto out;
3153 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003155 else if (*(args[myidx])) {
3156 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3157 file, linenum, args[0], args[myidx]);
3158 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003159 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003160 goto out;
3161 }
Emeric Brun97679e72010-09-23 17:56:44 +02003162 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003163 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003164 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003165 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003166
Emeric Brunb982a3d2010-01-04 15:45:53 +01003167 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3168 rule->cond = cond;
3169 rule->expr = expr;
3170 rule->flags = flags;
3171 rule->table.name = name ? strdup(name) : NULL;
3172 LIST_INIT(&rule->list);
3173 if (flags & STK_ON_RSP)
3174 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3175 else
3176 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003181
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3183 curproxy->uri_auth = NULL; /* we must detach from the default config */
3184
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003185 if (!*args[1]) {
3186 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003187 } else if (!strcmp(args[1], "admin")) {
3188 struct stats_admin_rule *rule;
3189
3190 if (curproxy == &defproxy) {
3191 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
3195
3196 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3197 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3198 err_code |= ERR_ALERT | ERR_ABORT;
3199 goto out;
3200 }
3201
3202 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3203 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3204 file, linenum, args[0], args[1]);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
3207 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003208 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3209 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3210 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003215 err_code |= warnif_cond_conflicts(cond,
3216 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3217 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003218
3219 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3220 rule->cond = cond;
3221 LIST_INIT(&rule->list);
3222 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 } else if (!strcmp(args[1], "uri")) {
3224 if (*(args[2]) == 0) {
3225 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3229 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_ABORT;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
3233 } else if (!strcmp(args[1], "realm")) {
3234 if (*(args[2]) == 0) {
3235 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_ABORT;
3241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003243 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003244 unsigned interval;
3245
3246 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3247 if (err) {
3248 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3249 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003252 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003256 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003257 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003258 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003259
3260 if (curproxy == &defproxy) {
3261 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265
3266 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3267 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3268 err_code |= ERR_ALERT | ERR_ABORT;
3269 goto out;
3270 }
3271
Willy Tarreauff011f22011-01-06 17:51:27 +01003272 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3273 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003274 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3275 file, linenum, args[0]);
3276 err_code |= ERR_WARN;
3277 }
3278
Willy Tarreauff011f22011-01-06 17:51:27 +01003279 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003280
Willy Tarreauff011f22011-01-06 17:51:27 +01003281 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003282 err_code |= ERR_ALERT | ERR_ABORT;
3283 goto out;
3284 }
3285
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003286 err_code |= warnif_cond_conflicts(rule->cond,
3287 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3288 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003289 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003290
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 } else if (!strcmp(args[1], "auth")) {
3292 if (*(args[2]) == 0) {
3293 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_ABORT;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301 } else if (!strcmp(args[1], "scope")) {
3302 if (*(args[2]) == 0) {
3303 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3307 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_ABORT;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 } else if (!strcmp(args[1], "enable")) {
3312 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_ABORT;
3315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003317 } else if (!strcmp(args[1], "hide-version")) {
3318 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003320 err_code |= ERR_ALERT | ERR_ABORT;
3321 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003322 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003323 } else if (!strcmp(args[1], "show-legends")) {
3324 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3325 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
3328 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003329 } else if (!strcmp(args[1], "show-node")) {
3330
3331 if (*args[2]) {
3332 int i;
3333 char c;
3334
3335 for (i=0; args[2][i]; i++) {
3336 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003337 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3338 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003339 break;
3340 }
3341
3342 if (!i || args[2][i]) {
3343 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3344 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3345 file, linenum, args[0], args[1]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349 }
3350
3351 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3352 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3353 err_code |= ERR_ALERT | ERR_ABORT;
3354 goto out;
3355 }
3356 } else if (!strcmp(args[1], "show-desc")) {
3357 char *desc = NULL;
3358
3359 if (*args[2]) {
3360 int i, len=0;
3361 char *d;
3362
3363 for(i=2; *args[i]; i++)
3364 len += strlen(args[i])+1;
3365
3366 desc = d = (char *)calloc(1, len);
3367
3368 d += sprintf(d, "%s", args[2]);
3369 for(i=3; *args[i]; i++)
3370 d += sprintf(d, " %s", args[i]);
3371 }
3372
3373 if (!*args[2] && !global.desc)
3374 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3375 file, linenum, args[1]);
3376 else {
3377 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3378 free(desc);
3379 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3380 err_code |= ERR_ALERT | ERR_ABORT;
3381 goto out;
3382 }
3383 free(desc);
3384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003386stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003387 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003388 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 }
3392 }
3393 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003394 int optnum;
3395
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003396 if (*(args[1]) == '\0') {
3397 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003402
3403 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3404 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003405 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3406 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3407 file, linenum, cfg_opts[optnum].name);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
Willy Tarreau93893792009-07-23 13:19:11 +02003411 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3412 err_code |= ERR_WARN;
3413 goto out;
3414 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003415
Willy Tarreau3842f002009-06-14 11:39:52 +02003416 curproxy->no_options &= ~cfg_opts[optnum].val;
3417 curproxy->options &= ~cfg_opts[optnum].val;
3418
3419 switch (kwm) {
3420 case KWM_STD:
3421 curproxy->options |= cfg_opts[optnum].val;
3422 break;
3423 case KWM_NO:
3424 curproxy->no_options |= cfg_opts[optnum].val;
3425 break;
3426 case KWM_DEF: /* already cleared */
3427 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003428 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003429
Willy Tarreau93893792009-07-23 13:19:11 +02003430 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003431 }
3432 }
3433
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003434 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3435 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003436 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3437 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3438 file, linenum, cfg_opts2[optnum].name);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
Willy Tarreau93893792009-07-23 13:19:11 +02003442 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3443 err_code |= ERR_WARN;
3444 goto out;
3445 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003446
Willy Tarreau3842f002009-06-14 11:39:52 +02003447 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3448 curproxy->options2 &= ~cfg_opts2[optnum].val;
3449
3450 switch (kwm) {
3451 case KWM_STD:
3452 curproxy->options2 |= cfg_opts2[optnum].val;
3453 break;
3454 case KWM_NO:
3455 curproxy->no_options2 |= cfg_opts2[optnum].val;
3456 break;
3457 case KWM_DEF: /* already cleared */
3458 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003459 }
Willy Tarreau93893792009-07-23 13:19:11 +02003460 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003461 }
3462 }
3463
Willy Tarreau3842f002009-06-14 11:39:52 +02003464 if (kwm != KWM_STD) {
3465 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003466 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003469 }
3470
Emeric Brun3a058f32009-06-30 18:26:00 +02003471 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003472 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003474 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003475 if (*(args[2]) != '\0') {
3476 if (!strcmp(args[2], "clf")) {
3477 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003478 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003479 } else {
3480 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003483 }
3484 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003485 if (curproxy->conf.logformat_string != default_http_log_format &&
3486 curproxy->conf.logformat_string != default_tcp_log_format &&
3487 curproxy->conf.logformat_string != clf_http_log_format)
3488 free(curproxy->conf.logformat_string);
3489 curproxy->conf.logformat_string = logformat;
3490
3491 free(curproxy->conf.lfs_file);
3492 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3493 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003494 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003495 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003497 if (curproxy->conf.logformat_string != default_http_log_format &&
3498 curproxy->conf.logformat_string != default_tcp_log_format &&
3499 curproxy->conf.logformat_string != clf_http_log_format)
3500 free(curproxy->conf.logformat_string);
3501 curproxy->conf.logformat_string = default_tcp_log_format;
3502
3503 free(curproxy->conf.lfs_file);
3504 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3505 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 else if (!strcmp(args[1], "tcpka")) {
3508 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003509 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003511
3512 if (curproxy->cap & PR_CAP_FE)
3513 curproxy->options |= PR_O_TCP_CLI_KA;
3514 if (curproxy->cap & PR_CAP_BE)
3515 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 }
3517 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_WARN;
3520
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003522 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003523 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003524 curproxy->options2 &= ~PR_O2_CHK_ANY;
3525 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 if (!*args[2]) { /* no argument */
3527 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3528 curproxy->check_len = strlen(DEF_CHECK_REQ);
3529 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003530 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 curproxy->check_req = (char *)malloc(reqlen);
3532 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003533 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003535 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 if (*args[4])
3537 reqlen += strlen(args[4]);
3538 else
3539 reqlen += strlen("HTTP/1.0");
3540
3541 curproxy->check_req = (char *)malloc(reqlen);
3542 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003543 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003545 }
3546 else if (!strcmp(args[1], "ssl-hello-chk")) {
3547 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003550
Willy Tarreaua534fea2008-08-03 12:19:50 +02003551 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003552 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003553 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003554 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
Willy Tarreau23677902007-05-08 23:50:35 +02003556 else if (!strcmp(args[1], "smtpchk")) {
3557 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003558 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003559 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003560 curproxy->options2 &= ~PR_O2_CHK_ANY;
3561 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003562
3563 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3564 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3565 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3566 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3567 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3568 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3569 curproxy->check_req = (char *)malloc(reqlen);
3570 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3571 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3572 } else {
3573 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3574 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3575 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3576 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3577 }
3578 }
3579 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003580 else if (!strcmp(args[1], "pgsql-check")) {
3581 /* use PostgreSQL request to check servers' health */
3582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3583 err_code |= ERR_WARN;
3584
3585 free(curproxy->check_req);
3586 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003587 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003588 curproxy->options2 |= PR_O2_PGSQL_CHK;
3589
3590 if (*(args[2])) {
3591 int cur_arg = 2;
3592
3593 while (*(args[cur_arg])) {
3594 if (strcmp(args[cur_arg], "user") == 0) {
3595 char * packet;
3596 uint32_t packet_len;
3597 uint32_t pv;
3598
3599 /* suboption header - needs additional argument for it */
3600 if (*(args[cur_arg+1]) == 0) {
3601 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3602 file, linenum, args[0], args[1], args[cur_arg]);
3603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
3605 }
3606
3607 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3608 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3609 pv = htonl(0x30000); /* protocol version 3.0 */
3610
3611 packet = (char*) calloc(1, packet_len);
3612
3613 memcpy(packet + 4, &pv, 4);
3614
3615 /* copy "user" */
3616 memcpy(packet + 8, "user", 4);
3617
3618 /* copy username */
3619 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3620
3621 free(curproxy->check_req);
3622 curproxy->check_req = packet;
3623 curproxy->check_len = packet_len;
3624
3625 packet_len = htonl(packet_len);
3626 memcpy(packet, &packet_len, 4);
3627 cur_arg += 2;
3628 } else {
3629 /* unknown suboption - catchall */
3630 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3631 file, linenum, args[0], args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 } /* end while loop */
3636 }
3637 }
3638
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003639 else if (!strcmp(args[1], "redis-check")) {
3640 /* use REDIS PING request to check servers' health */
3641 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3642 err_code |= ERR_WARN;
3643
3644 free(curproxy->check_req);
3645 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003646 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003647 curproxy->options2 |= PR_O2_REDIS_CHK;
3648
3649 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3650 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3651 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3652 }
3653
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003654 else if (!strcmp(args[1], "mysql-check")) {
3655 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3657 err_code |= ERR_WARN;
3658
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003659 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003660 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003661 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003662 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003663
3664 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3665 * const char mysql40_client_auth_pkt[] = {
3666 * "\x0e\x00\x00" // packet length
3667 * "\x01" // packet number
3668 * "\x00\x00" // client capabilities
3669 * "\x00\x00\x01" // max packet
3670 * "haproxy\x00" // username (null terminated string)
3671 * "\x00" // filler (always 0x00)
3672 * "\x01\x00\x00" // packet length
3673 * "\x00" // packet number
3674 * "\x01" // COM_QUIT command
3675 * };
3676 */
3677
3678 if (*(args[2])) {
3679 int cur_arg = 2;
3680
3681 while (*(args[cur_arg])) {
3682 if (strcmp(args[cur_arg], "user") == 0) {
3683 char *mysqluser;
3684 int packetlen, reqlen, userlen;
3685
3686 /* suboption header - needs additional argument for it */
3687 if (*(args[cur_arg+1]) == 0) {
3688 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3689 file, linenum, args[0], args[1], args[cur_arg]);
3690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
3692 }
3693 mysqluser = args[cur_arg + 1];
3694 userlen = strlen(mysqluser);
3695 packetlen = userlen + 7;
3696 reqlen = packetlen + 9;
3697
3698 free(curproxy->check_req);
3699 curproxy->check_req = (char *)calloc(1, reqlen);
3700 curproxy->check_len = reqlen;
3701
3702 snprintf(curproxy->check_req, 4, "%c%c%c",
3703 ((unsigned char) packetlen & 0xff),
3704 ((unsigned char) (packetlen >> 8) & 0xff),
3705 ((unsigned char) (packetlen >> 16) & 0xff));
3706
3707 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003708 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003709 curproxy->check_req[8] = 1;
3710 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3711 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3712 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3713 cur_arg += 2;
3714 } else {
3715 /* unknown suboption - catchall */
3716 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3717 file, linenum, args[0], args[1]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 } /* end while loop */
3722 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003723 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003724 else if (!strcmp(args[1], "ldap-check")) {
3725 /* use LDAP request to check servers' health */
3726 free(curproxy->check_req);
3727 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003728 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003729 curproxy->options2 |= PR_O2_LDAP_CHK;
3730
3731 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3732 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3733 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3734 }
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
Willy Tarreau2f075e92013-12-03 11:11:34 +01004953 /* note: check type will be set during the config review phase */
4954 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09004955 if (ret) {
4956 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004957 goto out;
4958 }
4959
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 newsrv->state |= SRV_CHECKED;
4961 }
4962
Simon Hormand60d6912013-11-25 10:46:36 +09004963 if (do_agent) {
4964 int ret;
4965
4966 if (!newsrv->agent.port) {
4967 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
4968 file, linenum, newsrv->id);
4969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
4971 }
4972
4973 if (!newsrv->agent.inter)
4974 newsrv->agent.inter = newsrv->check.inter;
4975
4976 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
4977 if (ret) {
4978 err_code |= ret;
4979 goto out;
4980 }
4981
4982 newsrv->state |= SRV_AGENT_CHECKED;
4983 }
4984
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004985 if (!defsrv) {
4986 if (newsrv->state & SRV_BACKUP)
4987 curproxy->srv_bck++;
4988 else
4989 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004990
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004991 newsrv->prev_state = newsrv->state;
4992 }
William Lallemanda73203e2012-03-12 12:48:57 +01004993 }
4994
4995 else if (strcmp(args[0], "unique-id-format") == 0) {
4996 if (!*(args[1])) {
4997 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
5000 }
William Lallemand3203ff42012-11-11 17:30:56 +01005001 if (*(args[2])) {
5002 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
5005 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005006 free(curproxy->conf.uniqueid_format_string);
5007 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005008
Willy Tarreau62a61232013-04-12 18:13:46 +02005009 free(curproxy->conf.uif_file);
5010 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5011 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005012 }
William Lallemanda73203e2012-03-12 12:48:57 +01005013
5014 else if (strcmp(args[0], "unique-id-header") == 0) {
5015 if (!*(args[1])) {
5016 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019 }
5020 free(curproxy->header_unique_id);
5021 curproxy->header_unique_id = strdup(args[1]);
5022 }
5023
William Lallemand723b73a2012-02-08 16:37:49 +01005024 else if (strcmp(args[0], "log-format") == 0) {
5025 if (!*(args[1])) {
5026 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
5029 }
William Lallemand3203ff42012-11-11 17:30:56 +01005030 if (*(args[2])) {
5031 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005035
Willy Tarreau62a61232013-04-12 18:13:46 +02005036 if (curproxy->conf.logformat_string != default_http_log_format &&
5037 curproxy->conf.logformat_string != default_tcp_log_format &&
5038 curproxy->conf.logformat_string != clf_http_log_format)
5039 free(curproxy->conf.logformat_string);
5040 curproxy->conf.logformat_string = strdup(args[1]);
5041
5042 free(curproxy->conf.lfs_file);
5043 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5044 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005045
5046 /* get a chance to improve log-format error reporting by
5047 * reporting the correct line-number when possible.
5048 */
5049 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5050 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5051 file, linenum, curproxy->id);
5052 err_code |= ERR_WARN;
5053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 }
William Lallemand723b73a2012-02-08 16:37:49 +01005055
William Lallemand0f99e342011-10-12 17:50:54 +02005056 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5057 /* delete previous herited or defined syslog servers */
5058 struct logsrv *back;
5059
5060 if (*(args[1]) != 0) {
5061 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
5064 }
5065
William Lallemand723b73a2012-02-08 16:37:49 +01005066 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5067 LIST_DEL(&tmplogsrv->list);
5068 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005069 }
5070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005072 struct logsrv *logsrv;
5073
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005075 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005076 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005077 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005078 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005079 LIST_INIT(&node->list);
5080 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
5083 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005084 struct sockaddr_storage *sk;
5085 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005086
5087 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088
William Lallemand0f99e342011-10-12 17:50:54 +02005089 logsrv->facility = get_log_facility(args[2]);
5090 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
5094
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 }
5096
William Lallemand0f99e342011-10-12 17:50:54 +02005097 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005099 logsrv->level = get_log_level(args[3]);
5100 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
5104
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
5106 }
5107
William Lallemand0f99e342011-10-12 17:50:54 +02005108 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005109 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005110 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005111 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005112 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
5115
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005116 }
5117 }
5118
Willy Tarreau902636f2013-03-10 19:44:48 +01005119 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005120 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005121 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005122 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005123 goto out;
5124 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005125
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005126 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005127
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005128 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005129 if (port1 != port2) {
5130 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5131 file, linenum, args[0], args[1]);
5132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
5135
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005136 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005137 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 }
William Lallemand0f99e342011-10-12 17:50:54 +02005139
5140 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 }
5142 else {
5143 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5144 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 }
5149 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005150 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005151 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005152 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005153 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005154
Willy Tarreau977b8e42006-12-29 14:19:17 +01005155 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005157
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005159 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5160 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005161 err_code |= ERR_ALERT | ERR_FATAL;
5162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005164
5165 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005166 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5167 free(curproxy->conn_src.iface_name);
5168 curproxy->conn_src.iface_name = NULL;
5169 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005170
Willy Tarreau902636f2013-03-10 19:44:48 +01005171 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005172 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005173 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005174 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005175 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005176 goto out;
5177 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005178
5179 proto = protocol_by_family(sk->ss_family);
5180 if (!proto || !proto->connect) {
5181 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005182 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005186
5187 if (port1 != port2) {
5188 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5189 file, linenum, args[0], args[1]);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193
Willy Tarreauef9a3602012-12-08 22:29:20 +01005194 curproxy->conn_src.source_addr = *sk;
5195 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005196
5197 cur_arg = 2;
5198 while (*(args[cur_arg])) {
5199 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005200#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5201#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005202 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005203 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5204 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005207 }
5208#endif
5209 if (!*args[cur_arg + 1]) {
5210 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5211 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005214 }
5215
5216 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005217 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5218 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005219 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005220 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5221 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005222 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5223 char *name, *end;
5224
5225 name = args[cur_arg+1] + 7;
5226 while (isspace(*name))
5227 name++;
5228
5229 end = name;
5230 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5231 end++;
5232
Willy Tarreauef9a3602012-12-08 22:29:20 +01005233 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5234 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5235 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5236 curproxy->conn_src.bind_hdr_len = end - name;
5237 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5238 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5239 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005240
5241 /* now look for an occurrence number */
5242 while (isspace(*end))
5243 end++;
5244 if (*end == ',') {
5245 end++;
5246 name = end;
5247 if (*end == '-')
5248 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005249 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005250 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005251 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005252 }
5253
Willy Tarreauef9a3602012-12-08 22:29:20 +01005254 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005255 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5256 " occurrences values smaller than %d.\n",
5257 file, linenum, MAX_HDR_HISTORY);
5258 err_code |= ERR_ALERT | ERR_FATAL;
5259 goto out;
5260 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005261 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005262 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005263
Willy Tarreau902636f2013-03-10 19:44:48 +01005264 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005265 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005266 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005267 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005268 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005269 goto out;
5270 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005271
5272 proto = protocol_by_family(sk->ss_family);
5273 if (!proto || !proto->connect) {
5274 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5275 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
5278 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005279
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005280 if (port1 != port2) {
5281 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5282 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005286 curproxy->conn_src.tproxy_addr = *sk;
5287 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005288 }
5289 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005290#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005291 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005292#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005293#else /* no TPROXY support */
5294 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005295 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005298#endif
5299 cur_arg += 2;
5300 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005301 }
5302
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005303 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5304#ifdef SO_BINDTODEVICE
5305 if (!*args[cur_arg + 1]) {
5306 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005310 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005311 free(curproxy->conn_src.iface_name);
5312 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5313 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005314 global.last_checks |= LSTCHK_NETADM;
5315#else
5316 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5317 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005320#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005321 cur_arg += 2;
5322 continue;
5323 }
5324 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005325 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005330 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5331 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5332 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005335 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005337 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005338 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5339 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005340 err_code |= ERR_ALERT | ERR_FATAL;
5341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343
5344 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005345 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005346 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005347 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 }
5350 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005351 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005352 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005353 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005354 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
5357 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005359 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005360 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
5364 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005366 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 }
5371 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005373 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005378 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005379 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005380 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005381 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005382 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005383 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005384 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005385 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005386 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005387 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005388 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005389 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005390 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005391 }
5392 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005393 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005394 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005395 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005396 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005397 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005400 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5402 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005406
5407 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005408 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005409 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005410 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
5413 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005414 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005415 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005416 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005417 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
5420 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005422 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005423 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
5427 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005429 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005430 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
5434 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005436 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005440 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005441 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005442 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005443 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005444 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005445 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005446 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005448 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005449 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005450
Willy Tarreaubaaee002006-06-26 02:48:02 +02005451 if (curproxy == &defproxy) {
5452 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005456 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005457 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459 if (*(args[1]) == 0) {
5460 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005464
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005465 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005466 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5467 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5468 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005472 err_code |= warnif_cond_conflicts(cond,
5473 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5474 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005475 }
5476 else if (*args[2]) {
5477 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5478 file, linenum, args[0], args[2]);
5479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
5481 }
5482
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005483 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005484 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005485 wl->s = strdup(args[1]);
5486 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005487 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 }
5489 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005490 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5492 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005496
Willy Tarreauade5ec42010-01-28 19:33:49 +01005497 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005498 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005499 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005500 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005502 }
5503 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005504 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005505 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005506 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005507 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 }
5510 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005511 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005512 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005513 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005514 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 }
5517 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005518 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5520 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
5524
Willy Tarreauade5ec42010-01-28 19:33:49 +01005525 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005526 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005527 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005528 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 }
5531 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005532 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005533 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005534 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005535 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 }
5538 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005539 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005540 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005541 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005542 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 }
5545 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005546 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005547
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 if (curproxy == &defproxy) {
5549 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005553 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005554 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556 if (*(args[1]) == 0) {
5557 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005560 }
5561
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005562 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005563 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5564 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5565 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005569 err_code |= warnif_cond_conflicts(cond,
5570 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5571 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005572 }
5573 else if (*args[2]) {
5574 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5575 file, linenum, args[0], args[2]);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 }
5579
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005580 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005581 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005582 wl->s = strdup(args[1]);
5583 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
5585 else if (!strcmp(args[0], "errorloc") ||
5586 !strcmp(args[0], "errorloc302") ||
5587 !strcmp(args[0], "errorloc303")) { /* error location */
5588 int errnum, errlen;
5589 char *err;
5590
Willy Tarreau977b8e42006-12-29 14:19:17 +01005591 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005593
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005595 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 }
5599
5600 errnum = atol(args[1]);
5601 if (!strcmp(args[0], "errorloc303")) {
5602 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5603 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5604 } else {
5605 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5606 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5607 }
5608
Willy Tarreau0f772532006-12-23 20:51:41 +01005609 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5610 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005611 chunk_destroy(&curproxy->errmsg[rc]);
5612 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005613 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005616
5617 if (rc >= HTTP_ERR_SIZE) {
5618 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5619 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 free(err);
5621 }
5622 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005623 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5624 int errnum, errlen, fd;
5625 char *err;
5626 struct stat stat;
5627
5628 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005629 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005630
5631 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005632 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005635 }
5636
5637 fd = open(args[2], O_RDONLY);
5638 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5639 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5640 file, linenum, args[2], args[1]);
5641 if (fd >= 0)
5642 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005645 }
5646
Willy Tarreau27a674e2009-08-17 07:23:33 +02005647 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005648 errlen = stat.st_size;
5649 } else {
5650 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005651 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005652 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005653 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005654 }
5655
5656 err = malloc(errlen); /* malloc() must succeed during parsing */
5657 errnum = read(fd, err, errlen);
5658 if (errnum != errlen) {
5659 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5660 file, linenum, args[2], args[1]);
5661 close(fd);
5662 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005665 }
5666 close(fd);
5667
5668 errnum = atol(args[1]);
5669 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5670 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005671 chunk_destroy(&curproxy->errmsg[rc]);
5672 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005673 break;
5674 }
5675 }
5676
5677 if (rc >= HTTP_ERR_SIZE) {
5678 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5679 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005680 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005681 free(err);
5682 }
5683 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005684 else if (!strcmp(args[0], "compression")) {
5685 struct comp *comp;
5686 if (curproxy->comp == NULL) {
5687 comp = calloc(1, sizeof(struct comp));
5688 curproxy->comp = comp;
5689 } else {
5690 comp = curproxy->comp;
5691 }
5692
5693 if (!strcmp(args[1], "algo")) {
5694 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005695 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005696
William Lallemand82fe75c2012-10-23 10:25:10 +02005697 cur_arg = 2;
5698 if (!*args[cur_arg]) {
5699 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5700 file, linenum, args[0]);
5701 err_code |= ERR_ALERT | ERR_FATAL;
5702 goto out;
5703 }
5704 while (*(args[cur_arg])) {
5705 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5706 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5707 file, linenum, args[0], args[cur_arg]);
5708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
5710 }
William Lallemand552df672012-11-07 13:21:47 +01005711 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5712 curproxy->comp->algos->end(&ctx);
5713 } else {
5714 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5715 file, linenum, args[0], args[cur_arg]);
5716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
5718 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005719 cur_arg ++;
5720 continue;
5721 }
5722 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005723 else if (!strcmp(args[1], "offload")) {
5724 comp->offload = 1;
5725 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005726 else if (!strcmp(args[1], "type")) {
5727 int cur_arg;
5728 cur_arg = 2;
5729 if (!*args[cur_arg]) {
5730 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5731 file, linenum, args[0]);
5732 err_code |= ERR_ALERT | ERR_FATAL;
5733 goto out;
5734 }
5735 while (*(args[cur_arg])) {
5736 comp_append_type(comp, args[cur_arg]);
5737 cur_arg ++;
5738 continue;
5739 }
5740 }
5741 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005742 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005743 file, linenum, args[0]);
5744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
5746 }
5747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005749 struct cfg_kw_list *kwl;
5750 int index;
5751
5752 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5753 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5754 if (kwl->kw[index].section != CFG_LISTEN)
5755 continue;
5756 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5757 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005758 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005759 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005760 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005763 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005764 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005765 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005766 err_code |= ERR_WARN;
5767 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005768 }
Willy Tarreau93893792009-07-23 13:19:11 +02005769 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005770 }
5771 }
5772 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005773
Willy Tarreau6daf3432008-01-22 16:44:08 +01005774 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005775 err_code |= ERR_ALERT | ERR_FATAL;
5776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
Willy Tarreau93893792009-07-23 13:19:11 +02005778 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005779 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005780 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781}
5782
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005783int
5784cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5785{
5786
5787 int err_code = 0;
5788 const char *err;
5789
5790 if (!strcmp(args[0], "userlist")) { /* new userlist */
5791 struct userlist *newul;
5792
5793 if (!*args[1]) {
5794 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5795 file, linenum, args[0]);
5796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
5798 }
5799
5800 err = invalid_char(args[1]);
5801 if (err) {
5802 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5803 file, linenum, *err, args[0], args[1]);
5804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
5806 }
5807
5808 for (newul = userlist; newul; newul = newul->next)
5809 if (!strcmp(newul->name, args[1])) {
5810 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5811 file, linenum, args[1]);
5812 err_code |= ERR_WARN;
5813 goto out;
5814 }
5815
5816 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5817 if (!newul) {
5818 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5819 err_code |= ERR_ALERT | ERR_ABORT;
5820 goto out;
5821 }
5822
5823 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5824 newul->name = strdup(args[1]);
5825
5826 if (!newul->groupusers | !newul->name) {
5827 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5828 err_code |= ERR_ALERT | ERR_ABORT;
5829 goto out;
5830 }
5831
5832 newul->next = userlist;
5833 userlist = newul;
5834
5835 } else if (!strcmp(args[0], "group")) { /* new group */
5836 int cur_arg, i;
5837 const char *err;
5838
5839 if (!*args[1]) {
5840 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5841 file, linenum, args[0]);
5842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
5844 }
5845
5846 err = invalid_char(args[1]);
5847 if (err) {
5848 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5849 file, linenum, *err, args[0], args[1]);
5850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
5852 }
5853
5854 for(i = 0; i < userlist->grpcnt; i++)
5855 if (!strcmp(userlist->groups[i], args[1])) {
5856 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5857 file, linenum, args[1], userlist->name);
5858 err_code |= ERR_ALERT;
5859 goto out;
5860 }
5861
5862 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5863 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5864 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
5867 }
5868
5869 cur_arg = 2;
5870
5871 while (*args[cur_arg]) {
5872 if (!strcmp(args[cur_arg], "users")) {
5873 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5874 cur_arg += 2;
5875 continue;
5876 } else {
5877 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5878 file, linenum, args[0]);
5879 err_code |= ERR_ALERT | ERR_FATAL;
5880 goto out;
5881 }
5882 }
5883
5884 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5885 } else if (!strcmp(args[0], "user")) { /* new user */
5886 struct auth_users *newuser;
5887 int cur_arg;
5888
5889 if (!*args[1]) {
5890 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5891 file, linenum, args[0]);
5892 err_code |= ERR_ALERT | ERR_FATAL;
5893 goto out;
5894 }
5895
5896 for (newuser = userlist->users; newuser; newuser = newuser->next)
5897 if (!strcmp(newuser->user, args[1])) {
5898 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5899 file, linenum, args[1], userlist->name);
5900 err_code |= ERR_ALERT;
5901 goto out;
5902 }
5903
5904 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5905 if (!newuser) {
5906 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5907 err_code |= ERR_ALERT | ERR_ABORT;
5908 goto out;
5909 }
5910
5911 newuser->user = strdup(args[1]);
5912
5913 newuser->next = userlist->users;
5914 userlist->users = newuser;
5915
5916 cur_arg = 2;
5917
5918 while (*args[cur_arg]) {
5919 if (!strcmp(args[cur_arg], "password")) {
5920#ifndef CONFIG_HAP_CRYPT
5921 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5922 file, linenum);
5923 err_code |= ERR_ALERT;
5924#endif
5925 newuser->pass = strdup(args[cur_arg + 1]);
5926 cur_arg += 2;
5927 continue;
5928 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5929 newuser->pass = strdup(args[cur_arg + 1]);
5930 newuser->flags |= AU_O_INSECURE;
5931 cur_arg += 2;
5932 continue;
5933 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005934 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005935 cur_arg += 2;
5936 continue;
5937 } else {
5938 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5939 file, linenum, args[0]);
5940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
5942 }
5943 }
5944 } else {
5945 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5946 err_code |= ERR_ALERT | ERR_FATAL;
5947 }
5948
5949out:
5950 return err_code;
5951}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005952
5953/*
5954 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005955 * Returns the error code, 0 if OK, or any combination of :
5956 * - ERR_ABORT: must abort ASAP
5957 * - ERR_FATAL: we can continue parsing but not start the service
5958 * - ERR_WARN: a warning has been emitted
5959 * - ERR_ALERT: an alert has been emitted
5960 * Only the two first ones can stop processing, the two others are just
5961 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005963int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005965 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005966 FILE *f;
5967 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005969 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 if ((f=fopen(file,"r")) == NULL)
5972 return -1;
5973
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005974 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005975 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005976 char *end;
5977 char *args[MAX_LINE_ARGS + 1];
5978 char *line = thisline;
5979
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 linenum++;
5981
5982 end = line + strlen(line);
5983
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005984 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5985 /* Check if we reached the limit and the last char is not \n.
5986 * Watch out for the last line without the terminating '\n'!
5987 */
5988 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005989 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005990 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005991 }
5992
Willy Tarreaubaaee002006-06-26 02:48:02 +02005993 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005994 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 line++;
5996
5997 arg = 0;
5998 args[arg] = line;
5999
6000 while (*line && arg < MAX_LINE_ARGS) {
6001 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6002 * C equivalent value. Other combinations left unchanged (eg: \1).
6003 */
6004 if (*line == '\\') {
6005 int skip = 0;
6006 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6007 *line = line[1];
6008 skip = 1;
6009 }
6010 else if (line[1] == 'r') {
6011 *line = '\r';
6012 skip = 1;
6013 }
6014 else if (line[1] == 'n') {
6015 *line = '\n';
6016 skip = 1;
6017 }
6018 else if (line[1] == 't') {
6019 *line = '\t';
6020 skip = 1;
6021 }
6022 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006023 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006024 unsigned char hex1, hex2;
6025 hex1 = toupper(line[2]) - '0';
6026 hex2 = toupper(line[3]) - '0';
6027 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6028 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6029 *line = (hex1<<4) + hex2;
6030 skip = 3;
6031 }
6032 else {
6033 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006034 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035 }
6036 }
6037 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006038 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039 end -= skip;
6040 }
6041 line++;
6042 }
6043 else if (*line == '#' || *line == '\n' || *line == '\r') {
6044 /* end of string, end of loop */
6045 *line = 0;
6046 break;
6047 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006048 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006050 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006051 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 line++;
6053 args[++arg] = line;
6054 }
6055 else {
6056 line++;
6057 }
6058 }
6059
6060 /* empty line */
6061 if (!**args)
6062 continue;
6063
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006064 if (*line) {
6065 /* we had to stop due to too many args.
6066 * Let's terminate the string, print the offending part then cut the
6067 * last arg.
6068 */
6069 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6070 line++;
6071 *line = '\0';
6072
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006073 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006074 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006075 err_code |= ERR_ALERT | ERR_FATAL;
6076 args[arg] = line;
6077 }
6078
Willy Tarreau540abe42007-05-02 20:50:16 +02006079 /* zero out remaining args and ensure that at least one entry
6080 * is zeroed out.
6081 */
6082 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006083 args[arg] = line;
6084 }
6085
Willy Tarreau3842f002009-06-14 11:39:52 +02006086 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006087 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006088 char *tmp;
6089
Willy Tarreau3842f002009-06-14 11:39:52 +02006090 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006091 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006092 for (arg=0; *args[arg+1]; arg++)
6093 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006094 *tmp = '\0'; // fix the next arg to \0
6095 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006096 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006097 else if (!strcmp(args[0], "default")) {
6098 kwm = KWM_DEF;
6099 for (arg=0; *args[arg+1]; arg++)
6100 args[arg] = args[arg+1]; // shift args after inversion
6101 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006102
William Lallemand0f99e342011-10-12 17:50:54 +02006103 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6104 strcmp(args[0], "log") != 0) {
6105 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006106 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006107 }
6108
Willy Tarreau977b8e42006-12-29 14:19:17 +01006109 if (!strcmp(args[0], "listen") ||
6110 !strcmp(args[0], "frontend") ||
6111 !strcmp(args[0], "backend") ||
6112 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006113 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006114 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006115 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006116 cursection = strdup(args[0]);
6117 }
6118 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006120 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006121 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006122 }
6123 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006124 confsect = CFG_USERLIST;
6125 free(cursection);
6126 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006127 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006128 else if (!strcmp(args[0], "peers")) {
6129 confsect = CFG_PEERS;
6130 free(cursection);
6131 cursection = strdup(args[0]);
6132 }
6133
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 /* else it's a section keyword */
6135
6136 switch (confsect) {
6137 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006138 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 break;
6140 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006141 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006143 case CFG_USERLIST:
6144 err_code |= cfg_parse_users(file, linenum, args, kwm);
6145 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006146 case CFG_PEERS:
6147 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6148 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006150 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006151 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006153
6154 if (err_code & ERR_ABORT)
6155 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006157 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006158 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006160 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006161}
6162
Willy Tarreaubb925012009-07-23 13:36:36 +02006163/*
6164 * Returns the error code, 0 if OK, or any combination of :
6165 * - ERR_ABORT: must abort ASAP
6166 * - ERR_FATAL: we can continue parsing but not start the service
6167 * - ERR_WARN: a warning has been emitted
6168 * - ERR_ALERT: an alert has been emitted
6169 * Only the two first ones can stop processing, the two others are just
6170 * indicators.
6171 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006172int check_config_validity()
6173{
6174 int cfgerr = 0;
6175 struct proxy *curproxy = NULL;
6176 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006177 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006178 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006179 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006180 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006182 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 /*
6184 * Now, check for the integrity of all that we have collected.
6185 */
6186
6187 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006188 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189
Willy Tarreau193b8c62012-11-22 00:17:38 +01006190 if (!global.tune.max_http_hdr)
6191 global.tune.max_http_hdr = MAX_HTTP_HDR;
6192
6193 if (!global.tune.cookie_len)
6194 global.tune.cookie_len = CAPTURE_LEN;
6195
6196 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6197
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006198 /* first, we will invert the proxy list order */
6199 curproxy = NULL;
6200 while (proxy) {
6201 struct proxy *next;
6202
6203 next = proxy->next;
6204 proxy->next = curproxy;
6205 curproxy = proxy;
6206 if (!next)
6207 break;
6208 proxy = next;
6209 }
6210
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006212 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006213 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006214 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006215 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006216 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006217 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006218 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006219
Willy Tarreau050536d2012-10-04 08:47:34 +02006220 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006221 /* proxy ID not set, use automatic numbering with first
6222 * spare entry starting with next_pxid.
6223 */
6224 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6225 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6226 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006227 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006228 next_pxid++;
6229
Willy Tarreau55ea7572007-06-17 19:56:27 +02006230
Willy Tarreaubaaee002006-06-26 02:48:02 +02006231 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006232 /* ensure we don't keep listeners uselessly bound */
6233 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006234 curproxy = curproxy->next;
6235 continue;
6236 }
6237
Willy Tarreau16a21472012-11-19 12:39:59 +01006238 /* number of processes this proxy is bound to */
6239 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6240
Willy Tarreauff01a212009-03-15 13:46:16 +01006241 switch (curproxy->mode) {
6242 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006243 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006244 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006245 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6246 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006247 cfgerr++;
6248 }
6249
6250 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006251 Warning("config : servers will be ignored for %s '%s'.\n",
6252 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006253 break;
6254
6255 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006256 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006257 break;
6258
6259 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006260 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006261 break;
6262 }
6263
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006264 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006265 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006266 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006267 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6268 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006269 cfgerr++;
6270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006272 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006273 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6274 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006275 cfgerr++;
6276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006278 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006279 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6280 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006281 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006282 }
6283 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006284 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006285 /* If no LB algo is set in a backend, and we're not in
6286 * transparent mode, dispatch mode nor proxy mode, we
6287 * want to use balance roundrobin by default.
6288 */
6289 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6290 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006291 }
6292 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006293
Willy Tarreau1620ec32011-08-06 17:05:02 +02006294 if (curproxy->options & PR_O_DISPATCH)
6295 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6296 else if (curproxy->options & PR_O_HTTP_PROXY)
6297 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6298 else if (curproxy->options & PR_O_TRANSP)
6299 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006300
Willy Tarreau1620ec32011-08-06 17:05:02 +02006301 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6302 if (curproxy->options & PR_O_DISABLE404) {
6303 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6304 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6305 err_code |= ERR_WARN;
6306 curproxy->options &= ~PR_O_DISABLE404;
6307 }
6308 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6309 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6310 "send-state", proxy_type_str(curproxy), curproxy->id);
6311 err_code |= ERR_WARN;
6312 curproxy->options &= ~PR_O2_CHK_SNDST;
6313 }
Willy Tarreauef781042010-01-27 11:53:01 +01006314 }
6315
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006316 /* if a default backend was specified, let's find it */
6317 if (curproxy->defbe.name) {
6318 struct proxy *target;
6319
Alex Williams96532db2009-11-01 21:27:13 -05006320 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006321 if (!target) {
6322 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6323 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006324 cfgerr++;
6325 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006326 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6327 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006328 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006329 } else {
6330 free(curproxy->defbe.name);
6331 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006332 /* we force the backend to be present on at least all of
6333 * the frontend's processes.
6334 */
6335 target->bind_proc = curproxy->bind_proc ?
6336 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006337
6338 /* Emit a warning if this proxy also has some servers */
6339 if (curproxy->srv) {
6340 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6341 curproxy->id);
6342 err_code |= ERR_WARN;
6343 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
6345 }
6346
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006347 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006348 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6349 /* map jump target for ACT_SETBE in req_rep chain */
6350 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006351 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006352 struct proxy *target;
6353
Willy Tarreaua496b602006-12-17 23:15:24 +01006354 if (exp->action != ACT_SETBE)
6355 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006356
Alex Williams96532db2009-11-01 21:27:13 -05006357 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006358 if (!target) {
6359 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6360 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006361 cfgerr++;
6362 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006363 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6364 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006365 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006366 } else {
6367 free((void *)exp->replace);
6368 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006369 /* we force the backend to be present on at least all of
6370 * the frontend's processes.
6371 */
6372 target->bind_proc = curproxy->bind_proc ?
6373 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006374 }
6375 }
6376 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006377
6378 /* find the target proxy for 'use_backend' rules */
6379 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006380 struct proxy *target;
6381
Alex Williams96532db2009-11-01 21:27:13 -05006382 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006383
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006384 if (!target) {
6385 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6386 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006387 cfgerr++;
6388 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006389 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6390 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006391 cfgerr++;
6392 } else {
6393 free((void *)rule->be.name);
6394 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006395 /* we force the backend to be present on at least all of
6396 * the frontend's processes.
6397 */
6398 target->bind_proc = curproxy->bind_proc ?
6399 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006400 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006401 }
6402
6403 /* find the target proxy for 'use_backend' rules */
6404 list_for_each_entry(srule, &curproxy->server_rules, list) {
6405 struct server *target = findserver(curproxy, srule->srv.name);
6406
6407 if (!target) {
6408 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6409 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6410 cfgerr++;
6411 continue;
6412 }
6413 free((void *)srule->srv.name);
6414 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006415 }
6416
Emeric Brunb982a3d2010-01-04 15:45:53 +01006417 /* find the target table for 'stick' rules */
6418 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6419 struct proxy *target;
6420
Emeric Brun1d33b292010-01-04 15:47:17 +01006421 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6422 if (mrule->flags & STK_IS_STORE)
6423 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6424
Emeric Brunb982a3d2010-01-04 15:45:53 +01006425 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006426 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006427 else
6428 target = curproxy;
6429
6430 if (!target) {
6431 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6432 curproxy->id, mrule->table.name);
6433 cfgerr++;
6434 }
6435 else if (target->table.size == 0) {
6436 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6437 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6438 cfgerr++;
6439 }
Willy Tarreau12785782012-04-27 21:37:17 +02006440 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6441 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006442 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6443 cfgerr++;
6444 }
6445 else {
6446 free((void *)mrule->table.name);
6447 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006448 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006449 }
6450 }
6451
6452 /* find the target table for 'store response' rules */
6453 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6454 struct proxy *target;
6455
Emeric Brun1d33b292010-01-04 15:47:17 +01006456 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6457
Emeric Brunb982a3d2010-01-04 15:45:53 +01006458 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006459 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006460 else
6461 target = curproxy;
6462
6463 if (!target) {
6464 Alert("Proxy '%s': unable to find store table '%s'.\n",
6465 curproxy->id, mrule->table.name);
6466 cfgerr++;
6467 }
6468 else if (target->table.size == 0) {
6469 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6470 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6471 cfgerr++;
6472 }
Willy Tarreau12785782012-04-27 21:37:17 +02006473 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6474 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006475 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6476 cfgerr++;
6477 }
6478 else {
6479 free((void *)mrule->table.name);
6480 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006481 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006482 }
6483 }
6484
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006485 /* find the target table for 'tcp-request' layer 4 rules */
6486 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6487 struct proxy *target;
6488
Willy Tarreaub4c84932013-07-23 19:15:30 +02006489 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006490 continue;
6491
6492 if (trule->act_prm.trk_ctr.table.n)
6493 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6494 else
6495 target = curproxy;
6496
6497 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006498 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6499 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006500 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006501 cfgerr++;
6502 }
6503 else if (target->table.size == 0) {
6504 Alert("Proxy '%s': table '%s' used but not configured.\n",
6505 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6506 cfgerr++;
6507 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006508 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6509 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6510 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 +01006511 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006512 cfgerr++;
6513 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006514 else {
6515 free(trule->act_prm.trk_ctr.table.n);
6516 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006517 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006518 * to pass a list of counters to track and allocate them right here using
6519 * stktable_alloc_data_type().
6520 */
6521 }
6522 }
6523
Willy Tarreaud1f96522010-08-03 19:34:32 +02006524 /* find the target table for 'tcp-request' layer 6 rules */
6525 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6526 struct proxy *target;
6527
Willy Tarreaub4c84932013-07-23 19:15:30 +02006528 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006529 continue;
6530
6531 if (trule->act_prm.trk_ctr.table.n)
6532 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6533 else
6534 target = curproxy;
6535
6536 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006537 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6538 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006539 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006540 cfgerr++;
6541 }
6542 else if (target->table.size == 0) {
6543 Alert("Proxy '%s': table '%s' used but not configured.\n",
6544 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6545 cfgerr++;
6546 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006547 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6548 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6549 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 +01006550 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006551 cfgerr++;
6552 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006553 else {
6554 free(trule->act_prm.trk_ctr.table.n);
6555 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006556 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006557 * to pass a list of counters to track and allocate them right here using
6558 * stktable_alloc_data_type().
6559 */
6560 }
6561 }
6562
Emeric Brun32da3c42010-09-23 18:39:19 +02006563 if (curproxy->table.peers.name) {
6564 struct peers *curpeers = peers;
6565
6566 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6567 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6568 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006569 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006570 break;
6571 }
6572 }
6573
6574 if (!curpeers) {
6575 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6576 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006577 free((void *)curproxy->table.peers.name);
6578 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006579 cfgerr++;
6580 }
6581 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006582 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6583 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006584 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006585 cfgerr++;
6586 }
6587 }
6588
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006589 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006590 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006591 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6592 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6593 "proxy", curproxy->id);
6594 cfgerr++;
6595 goto out_uri_auth_compat;
6596 }
6597
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006598 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006599 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006600 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006601 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006602
Willy Tarreau95fa4692010-02-01 13:05:50 +01006603 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6604 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006605
6606 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006607 uri_auth_compat_req[i++] = "realm";
6608 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6609 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006610
Willy Tarreau95fa4692010-02-01 13:05:50 +01006611 uri_auth_compat_req[i++] = "unless";
6612 uri_auth_compat_req[i++] = "{";
6613 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6614 uri_auth_compat_req[i++] = "}";
6615 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006616
Willy Tarreauff011f22011-01-06 17:51:27 +01006617 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6618 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006619 cfgerr++;
6620 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006621 }
6622
Willy Tarreauff011f22011-01-06 17:51:27 +01006623 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006624
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006625 if (curproxy->uri_auth->auth_realm) {
6626 free(curproxy->uri_auth->auth_realm);
6627 curproxy->uri_auth->auth_realm = NULL;
6628 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006629
6630 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006631 }
6632out_uri_auth_compat:
6633
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006634 /* compile the log format */
6635 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006636 if (curproxy->conf.logformat_string != default_http_log_format &&
6637 curproxy->conf.logformat_string != default_tcp_log_format &&
6638 curproxy->conf.logformat_string != clf_http_log_format)
6639 free(curproxy->conf.logformat_string);
6640 curproxy->conf.logformat_string = NULL;
6641 free(curproxy->conf.lfs_file);
6642 curproxy->conf.lfs_file = NULL;
6643 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006644 }
6645
Willy Tarreau62a61232013-04-12 18:13:46 +02006646 if (curproxy->conf.logformat_string) {
6647 curproxy->conf.args.ctx = ARGC_LOG;
6648 curproxy->conf.args.file = curproxy->conf.lfs_file;
6649 curproxy->conf.args.line = curproxy->conf.lfs_line;
6650 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006651 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006652 curproxy->conf.args.file = NULL;
6653 curproxy->conf.args.line = 0;
6654 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006655
Willy Tarreau62a61232013-04-12 18:13:46 +02006656 if (curproxy->conf.uniqueid_format_string) {
6657 curproxy->conf.args.ctx = ARGC_UIF;
6658 curproxy->conf.args.file = curproxy->conf.uif_file;
6659 curproxy->conf.args.line = curproxy->conf.uif_line;
6660 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006661 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006662 curproxy->conf.args.file = NULL;
6663 curproxy->conf.args.line = 0;
6664 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006665
6666 /* only now we can check if some args remain unresolved */
6667 cfgerr += smp_resolve_args(curproxy);
6668 if (!cfgerr)
6669 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006670
Willy Tarreau2738a142006-07-08 17:28:09 +02006671 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006672 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006673 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006674 (!curproxy->timeout.connect ||
6675 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006676 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006677 " | While not properly invalid, you will certainly encounter various problems\n"
6678 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006679 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006680 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006681 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006682 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006683
Willy Tarreau1fa31262007-12-03 00:36:16 +01006684 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6685 * We must still support older configurations, so let's find out whether those
6686 * parameters have been set or must be copied from contimeouts.
6687 */
6688 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006689 if (!curproxy->timeout.tarpit ||
6690 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006691 /* tarpit timeout not set. We search in the following order:
6692 * default.tarpit, curr.connect, default.connect.
6693 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006694 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006695 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006696 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006697 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006698 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006699 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006700 }
6701 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006702 (!curproxy->timeout.queue ||
6703 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006704 /* queue timeout not set. We search in the following order:
6705 * default.queue, curr.connect, default.connect.
6706 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006707 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006708 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006709 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006710 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006711 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006712 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006713 }
6714 }
6715
Willy Tarreau1620ec32011-08-06 17:05:02 +02006716 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006717 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6718 curproxy->check_req = (char *)malloc(curproxy->check_len);
6719 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006720 }
6721
Willy Tarreau193b8c62012-11-22 00:17:38 +01006722 /* ensure that cookie capture length is not too large */
6723 if (curproxy->capture_len >= global.tune.cookie_len) {
6724 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6725 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6726 err_code |= ERR_WARN;
6727 curproxy->capture_len = global.tune.cookie_len - 1;
6728 }
6729
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006730 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006731 if (curproxy->nb_req_cap) {
6732 if (curproxy->mode == PR_MODE_HTTP) {
6733 curproxy->req_cap_pool = create_pool("ptrcap",
6734 curproxy->nb_req_cap * sizeof(char *),
6735 MEM_F_SHARED);
6736 } else {
6737 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6738 proxy_type_str(curproxy), curproxy->id);
6739 err_code |= ERR_WARN;
6740 curproxy->to_log &= ~LW_REQHDR;
6741 curproxy->nb_req_cap = 0;
6742 }
6743 }
6744
6745 if (curproxy->nb_rsp_cap) {
6746 if (curproxy->mode == PR_MODE_HTTP) {
6747 curproxy->rsp_cap_pool = create_pool("ptrcap",
6748 curproxy->nb_rsp_cap * sizeof(char *),
6749 MEM_F_SHARED);
6750 } else {
6751 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6752 proxy_type_str(curproxy), curproxy->id);
6753 err_code |= ERR_WARN;
6754 curproxy->to_log &= ~LW_REQHDR;
6755 curproxy->nb_rsp_cap = 0;
6756 }
6757 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006758
Willy Tarreaubaaee002006-06-26 02:48:02 +02006759 /* first, we will invert the servers list order */
6760 newsrv = NULL;
6761 while (curproxy->srv) {
6762 struct server *next;
6763
6764 next = curproxy->srv->next;
6765 curproxy->srv->next = newsrv;
6766 newsrv = curproxy->srv;
6767 if (!next)
6768 break;
6769 curproxy->srv = next;
6770 }
6771
Willy Tarreaudd701652010-05-25 23:03:02 +02006772 /* assign automatic UIDs to servers which don't have one yet */
6773 next_id = 1;
6774 newsrv = curproxy->srv;
6775 while (newsrv != NULL) {
6776 if (!newsrv->puid) {
6777 /* server ID not set, use automatic numbering with first
6778 * spare entry starting with next_svid.
6779 */
6780 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6781 newsrv->conf.id.key = newsrv->puid = next_id;
6782 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6783 }
6784 next_id++;
6785 newsrv = newsrv->next;
6786 }
6787
Willy Tarreau20697042007-11-15 23:26:18 +01006788 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006789 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006790
Willy Tarreau62c3be22012-01-20 13:12:32 +01006791 /*
6792 * If this server supports a maxconn parameter, it needs a dedicated
6793 * tasks to fill the emptied slots when a connection leaves.
6794 * Also, resolve deferred tracking dependency if needed.
6795 */
6796 newsrv = curproxy->srv;
6797 while (newsrv != NULL) {
6798 if (newsrv->minconn > newsrv->maxconn) {
6799 /* Only 'minconn' was specified, or it was higher than or equal
6800 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6801 * this will avoid further useless expensive computations.
6802 */
6803 newsrv->maxconn = newsrv->minconn;
6804 } else if (newsrv->maxconn && !newsrv->minconn) {
6805 /* minconn was not specified, so we set it to maxconn */
6806 newsrv->minconn = newsrv->maxconn;
6807 }
6808
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006809#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006810 if (newsrv->use_ssl || newsrv->check.use_ssl)
6811 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006812#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006813
Willy Tarreau2f075e92013-12-03 11:11:34 +01006814 /* set the check type on the server */
6815 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6816
Willy Tarreau62c3be22012-01-20 13:12:32 +01006817 if (newsrv->trackit) {
6818 struct proxy *px;
6819 struct server *srv;
6820 char *pname, *sname;
6821
6822 pname = newsrv->trackit;
6823 sname = strrchr(pname, '/');
6824
6825 if (sname)
6826 *sname++ = '\0';
6827 else {
6828 sname = pname;
6829 pname = NULL;
6830 }
6831
6832 if (pname) {
6833 px = findproxy(pname, PR_CAP_BE);
6834 if (!px) {
6835 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6836 proxy_type_str(curproxy), curproxy->id,
6837 newsrv->id, pname);
6838 cfgerr++;
6839 goto next_srv;
6840 }
6841 } else
6842 px = curproxy;
6843
6844 srv = findserver(px, sname);
6845 if (!srv) {
6846 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6847 proxy_type_str(curproxy), curproxy->id,
6848 newsrv->id, sname);
6849 cfgerr++;
6850 goto next_srv;
6851 }
6852
6853 if (!(srv->state & SRV_CHECKED)) {
6854 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6855 "tracking as it does not have checks enabled.\n",
6856 proxy_type_str(curproxy), curproxy->id,
6857 newsrv->id, px->id, srv->id);
6858 cfgerr++;
6859 goto next_srv;
6860 }
6861
6862 if (curproxy != px &&
6863 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6864 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6865 "tracking: disable-on-404 option inconsistency.\n",
6866 proxy_type_str(curproxy), curproxy->id,
6867 newsrv->id, px->id, srv->id);
6868 cfgerr++;
6869 goto next_srv;
6870 }
6871
6872 /* if the other server is forced disabled, we have to do the same here */
6873 if (srv->state & SRV_MAINTAIN) {
6874 newsrv->state |= SRV_MAINTAIN;
6875 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006876 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006877 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006878 }
6879
6880 newsrv->track = srv;
6881 newsrv->tracknext = srv->tracknext;
6882 srv->tracknext = newsrv;
6883
6884 free(newsrv->trackit);
6885 newsrv->trackit = NULL;
6886 }
6887 next_srv:
6888 newsrv = newsrv->next;
6889 }
6890
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006891 /* We have to initialize the server lookup mechanism depending
6892 * on what LB algorithm was choosen.
6893 */
6894
6895 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6896 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6897 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006898 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6899 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6900 init_server_map(curproxy);
6901 } else {
6902 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6903 fwrr_init_server_groups(curproxy);
6904 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006905 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006906
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006907 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006908 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6909 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6910 fwlc_init_server_tree(curproxy);
6911 } else {
6912 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6913 fas_init_server_tree(curproxy);
6914 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006915 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006916
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006917 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006918 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6919 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6920 chash_init_server_tree(curproxy);
6921 } else {
6922 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6923 init_server_map(curproxy);
6924 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006925 break;
6926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006927
6928 if (curproxy->options & PR_O_LOGASAP)
6929 curproxy->to_log &= ~LW_BYTES;
6930
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006931 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006932 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006933 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6934 proxy_type_str(curproxy), curproxy->id);
6935 err_code |= ERR_WARN;
6936 }
6937
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006938 if (curproxy->mode != PR_MODE_HTTP) {
6939 int optnum;
6940
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006941 if (curproxy->uri_auth) {
6942 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6943 proxy_type_str(curproxy), curproxy->id);
6944 err_code |= ERR_WARN;
6945 curproxy->uri_auth = NULL;
6946 }
6947
Willy Tarreau87cf5142011-08-19 22:57:24 +02006948 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006949 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6950 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6951 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006952 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006953 }
6954
6955 if (curproxy->options & PR_O_ORGTO) {
6956 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6957 "originalto", proxy_type_str(curproxy), curproxy->id);
6958 err_code |= ERR_WARN;
6959 curproxy->options &= ~PR_O_ORGTO;
6960 }
6961
6962 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6963 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6964 (curproxy->cap & cfg_opts[optnum].cap) &&
6965 (curproxy->options & cfg_opts[optnum].val)) {
6966 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6967 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6968 err_code |= ERR_WARN;
6969 curproxy->options &= ~cfg_opts[optnum].val;
6970 }
6971 }
6972
6973 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6974 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6975 (curproxy->cap & cfg_opts2[optnum].cap) &&
6976 (curproxy->options2 & cfg_opts2[optnum].val)) {
6977 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6978 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6979 err_code |= ERR_WARN;
6980 curproxy->options2 &= ~cfg_opts2[optnum].val;
6981 }
6982 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006983
Pieter Baauwd551fb52013-05-08 22:49:23 +02006984#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006985 if (curproxy->conn_src.bind_hdr_occ) {
6986 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006987 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006988 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006989 err_code |= ERR_WARN;
6990 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006991#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006992 }
6993
Willy Tarreaubaaee002006-06-26 02:48:02 +02006994 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006995 * ensure that we're not cross-dressing a TCP server into HTTP.
6996 */
6997 newsrv = curproxy->srv;
6998 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006999 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007000 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7001 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007002 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007003 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007004
Willy Tarreau0cec3312011-10-31 13:49:26 +01007005 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7006 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7007 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7008 err_code |= ERR_WARN;
7009 }
7010
Willy Tarreau82ffa392013-08-13 17:19:08 +02007011 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7012 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7013 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7014 err_code |= ERR_WARN;
7015 }
7016
Pieter Baauwd551fb52013-05-08 22:49:23 +02007017#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007018 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7019 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007020 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 +01007021 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007022 err_code |= ERR_WARN;
7023 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007024#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007025 newsrv = newsrv->next;
7026 }
7027
Willy Tarreauc1a21672009-08-16 22:37:44 +02007028 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007029 if (!curproxy->accept)
7030 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007031
Willy Tarreauc1a21672009-08-16 22:37:44 +02007032 if (curproxy->tcp_req.inspect_delay ||
7033 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007034 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007035
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007036 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007037 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007038 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007039 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007040
7041 /* both TCP and HTTP must check switching rules */
7042 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7043 }
7044
7045 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007046 if (curproxy->tcp_req.inspect_delay ||
7047 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7048 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7049
Emeric Brun97679e72010-09-23 17:56:44 +02007050 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7051 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7052
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007053 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007054 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007055 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007056 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007057
7058 /* If the backend does requires RDP cookie persistence, we have to
7059 * enable the corresponding analyser.
7060 */
7061 if (curproxy->options2 & PR_O2_RDPC_PRST)
7062 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7063 }
7064
Emeric Brunc52962f2012-11-15 18:28:02 +01007065#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007066 /* Configure SSL for each bind line.
7067 * Note: if configuration fails at some point, the ->ctx member
7068 * remains NULL so that listeners can later detach.
7069 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007070 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007071 if (!bind_conf->is_ssl) {
7072 if (bind_conf->default_ctx) {
7073 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7074 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7075 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007076 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007077 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007078 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007079 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007080 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007081 cfgerr++;
7082 continue;
7083 }
7084
Emeric Brun4b3091e2012-09-24 15:48:52 +02007085 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007086 Alert("Unable to allocate SSL session cache.\n");
7087 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007088 continue;
7089 }
7090
Emeric Brunfc0421f2012-09-07 17:30:07 +02007091 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007092 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007093 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007094#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007095
Willy Tarreaue6b98942007-10-29 01:09:36 +01007096 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007097 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007098 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007099 if (!listener->luid) {
7100 /* listener ID not set, use automatic numbering with first
7101 * spare entry starting with next_luid.
7102 */
7103 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7104 listener->conf.id.key = listener->luid = next_id;
7105 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007106 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007107 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007108
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007109 /* enable separate counters */
7110 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7111 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007112 if (!listener->name)
7113 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007114 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007115
Willy Tarreaue6b98942007-10-29 01:09:36 +01007116 if (curproxy->options & PR_O_TCP_NOLING)
7117 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007118 if (!listener->maxconn)
7119 listener->maxconn = curproxy->maxconn;
7120 if (!listener->backlog)
7121 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007122 if (!listener->maxaccept)
7123 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7124
7125 /* we want to have an optimal behaviour on single process mode to
7126 * maximize the work at once, but in multi-process we want to keep
7127 * some fairness between processes, so we target half of the max
7128 * number of events to be balanced over all the processes the proxy
7129 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7130 * used to disable the limit.
7131 */
7132 if (listener->maxaccept > 0) {
7133 if (nbproc > 1)
7134 listener->maxaccept = (listener->maxaccept + 1) / 2;
7135 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7136 }
7137
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007138 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007139 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007140 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007141 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007142
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007143 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7144 listener->options |= LI_O_TCP_RULES;
7145
Willy Tarreaude3041d2010-05-31 10:56:17 +02007146 if (curproxy->mon_mask.s_addr)
7147 listener->options |= LI_O_CHK_MONNET;
7148
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007149 /* smart accept mode is automatic in HTTP mode */
7150 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007151 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007152 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7153 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007154 }
7155
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007156 /* Release unused SSL configs */
7157 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7158 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007159 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007160#ifdef USE_OPENSSL
7161 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007162 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007163 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007164 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007165 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007166#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007167 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007168
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007169 /* Check multi-process mode compatibility for the current proxy */
7170 if (global.nbproc > 1) {
7171 int nbproc = 0;
7172 if (curproxy->bind_proc) {
7173 int proc;
7174 for (proc = 0; proc < global.nbproc; proc++) {
7175 if (curproxy->bind_proc & (1 << proc)) {
7176 nbproc++;
7177 }
7178 }
7179 } else {
7180 nbproc = global.nbproc;
7181 }
7182 if (curproxy->table.peers.name) {
7183 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7184 curproxy->id);
7185 cfgerr++;
7186 }
7187 if (nbproc > 1) {
7188 if (curproxy->uri_auth) {
7189 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7190 curproxy->id);
7191 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7192 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7193 curproxy->id);
7194 }
7195 }
7196 if (curproxy->appsession_name) {
7197 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7198 curproxy->id);
7199 }
7200 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7201 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7202 curproxy->id);
7203 }
7204 }
7205 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007206
7207 /* create the task associated with the proxy */
7208 curproxy->task = task_new();
7209 if (curproxy->task) {
7210 curproxy->task->context = curproxy;
7211 curproxy->task->process = manage_proxy;
7212 /* no need to queue, it will be done automatically if some
7213 * listener gets limited.
7214 */
7215 curproxy->task->expire = TICK_ETERNITY;
7216 } else {
7217 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7218 curproxy->id);
7219 cfgerr++;
7220 }
7221
Willy Tarreaubaaee002006-06-26 02:48:02 +02007222 curproxy = curproxy->next;
7223 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007224
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007225 /* Check multi-process mode compatibility */
7226 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007227 if (global.stats_fe && !global.stats_fe->bind_proc) {
7228 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 +01007229 }
7230 }
7231
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007232 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7233 struct auth_users *curuser;
7234 int g;
7235
7236 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7237 unsigned int group_mask = 0;
7238 char *group = NULL;
7239
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007240 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007241 continue;
7242
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007243 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007244
7245 for (g = 0; g < curuserlist->grpcnt; g++)
7246 if (!strcmp(curuserlist->groups[g], group))
7247 break;
7248
7249 if (g == curuserlist->grpcnt) {
7250 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7251 curuserlist->name, group, curuser->user);
7252 err_code |= ERR_ALERT | ERR_FATAL;
7253 goto out;
7254 }
7255
7256 group_mask |= (1 << g);
7257 }
7258
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007259 free(curuser->u.groups);
7260 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007261 }
7262
7263 for (g = 0; g < curuserlist->grpcnt; g++) {
7264 char *user = NULL;
7265
7266 if (!curuserlist->groupusers[g])
7267 continue;
7268
7269 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7270 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7271 if (!strcmp(curuser->user, user))
7272 break;
7273
7274 if (!curuser) {
7275 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7276 curuserlist->name, user, curuserlist->groups[g]);
7277 err_code |= ERR_ALERT | ERR_FATAL;
7278 goto out;
7279 }
7280
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007281 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007282 }
7283
7284 free(curuserlist->groupusers[g]);
7285 }
7286
7287 free(curuserlist->groupusers);
7288
7289#ifdef DEBUG_AUTH
7290 for (g = 0; g < curuserlist->grpcnt; g++) {
7291 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7292
7293 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007294 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007295 fprintf(stderr, " %s", curuser->user);
7296 }
7297
7298 fprintf(stderr, "\n");
7299 }
7300#endif
7301
Willy Tarreaufbb78422011-06-05 15:38:35 +02007302 }
7303
7304 /* automatically compute fullconn if not set. We must not do it in the
7305 * loop above because cross-references are not yet fully resolved.
7306 */
7307 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7308 /* If <fullconn> is not set, let's set it to 10% of the sum of
7309 * the possible incoming frontend's maxconns.
7310 */
7311 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7312 struct proxy *fe;
7313 int total = 0;
7314
7315 /* sum up the number of maxconns of frontends which
7316 * reference this backend at least once or which are
7317 * the same one ('listen').
7318 */
7319 for (fe = proxy; fe; fe = fe->next) {
7320 struct switching_rule *rule;
7321 struct hdr_exp *exp;
7322 int found = 0;
7323
7324 if (!(fe->cap & PR_CAP_FE))
7325 continue;
7326
7327 if (fe == curproxy) /* we're on a "listen" instance */
7328 found = 1;
7329
7330 if (fe->defbe.be == curproxy) /* "default_backend" */
7331 found = 1;
7332
7333 /* check if a "use_backend" rule matches */
7334 if (!found) {
7335 list_for_each_entry(rule, &fe->switching_rules, list) {
7336 if (rule->be.backend == curproxy) {
7337 found = 1;
7338 break;
7339 }
7340 }
7341 }
7342
7343 /* check if a "reqsetbe" rule matches */
7344 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7345 if (exp->action == ACT_SETBE &&
7346 (struct proxy *)exp->replace == curproxy) {
7347 found = 1;
7348 break;
7349 }
7350 }
7351
7352 /* now we've checked all possible ways to reference a backend
7353 * from a frontend.
7354 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007355 if (!found)
7356 continue;
7357 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007358 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007359 /* we have the sum of the maxconns in <total>. We only
7360 * keep 10% of that sum to set the default fullconn, with
7361 * a hard minimum of 1 (to avoid a divide by zero).
7362 */
7363 curproxy->fullconn = (total + 9) / 10;
7364 if (!curproxy->fullconn)
7365 curproxy->fullconn = 1;
7366 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007367 }
7368
Willy Tarreau056f5682010-06-06 15:51:11 +02007369 /* initialize stick-tables on backend capable proxies. This must not
7370 * be done earlier because the data size may be discovered while parsing
7371 * other proxies.
7372 */
7373 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007374 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007375
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007376 /*
7377 * Recount currently required checks.
7378 */
7379
7380 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7381 int optnum;
7382
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007383 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7384 if (curproxy->options & cfg_opts[optnum].val)
7385 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007386
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007387 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7388 if (curproxy->options2 & cfg_opts2[optnum].val)
7389 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007390 }
7391
Willy Tarreau122541c2011-09-07 21:24:49 +02007392 if (peers) {
7393 struct peers *curpeers = peers, **last;
7394 struct peer *p, *pb;
7395
7396 /* Remove all peers sections which don't have a valid listener.
7397 * This can happen when a peers section is never referenced and
7398 * does not contain a local peer.
7399 */
7400 last = &peers;
7401 while (*last) {
7402 curpeers = *last;
7403 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007404 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007405 last = &curpeers->next;
7406 continue;
7407 }
7408
7409 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7410 curpeers->id, localpeer);
7411
7412 p = curpeers->remote;
7413 while (p) {
7414 pb = p->next;
7415 free(p->id);
7416 free(p);
7417 p = pb;
7418 }
7419
7420 /* Destroy and unlink this curpeers section.
7421 * Note: curpeers is backed up into *last.
7422 */
7423 free(curpeers->id);
7424 curpeers = curpeers->next;
7425 free(*last);
7426 *last = curpeers;
7427 }
7428 }
7429
Willy Tarreau34eb6712011-10-24 18:15:04 +02007430 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007431 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007432 MEM_F_SHARED);
7433
Willy Tarreaubb925012009-07-23 13:36:36 +02007434 if (cfgerr > 0)
7435 err_code |= ERR_ALERT | ERR_FATAL;
7436 out:
7437 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007438}
7439
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007440/*
7441 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7442 * parsing sessions.
7443 */
7444void cfg_register_keywords(struct cfg_kw_list *kwl)
7445{
7446 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7447}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007448
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007449/*
7450 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7451 */
7452void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7453{
7454 LIST_DEL(&kwl->list);
7455 LIST_INIT(&kwl->list);
7456}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007457
7458/*
7459 * Local variables:
7460 * c-indent-level: 8
7461 * c-basic-offset: 8
7462 * End:
7463 */