blob: b16c310b6e1146ead5c919edb40ad993ddf20609 [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;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001328 defproxy.defsrv.rise = DEF_RISETIME;
1329 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001330 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001331 defproxy.defsrv.maxqueue = 0;
1332 defproxy.defsrv.minconn = 0;
1333 defproxy.defsrv.maxconn = 0;
1334 defproxy.defsrv.slowstart = 0;
1335 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1336 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1337 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338}
1339
Willy Tarreauade5ec42010-01-28 19:33:49 +01001340
1341static int create_cond_regex_rule(const char *file, int line,
1342 struct proxy *px, int dir, int action, int flags,
1343 const char *cmd, const char *reg, const char *repl,
1344 const char **cond_start)
1345{
1346 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348 const char *err;
1349 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001350 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001351
1352 if (px == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto err;
1356 }
1357
1358 if (*reg == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1365 err_code |= ERR_WARN;
1366
Willy Tarreau5321c422010-01-28 20:35:13 +01001367 if (cond_start &&
1368 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001369 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1370 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1371 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375 }
1376 else if (cond_start && **cond_start) {
1377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1378 file, line, cmd, *cond_start);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001383 err_code |= warnif_cond_conflicts(cond,
1384 (dir == SMP_OPT_DIR_REQ) ?
1385 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1386 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1387 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001388
Willy Tarreauade5ec42010-01-28 19:33:49 +01001389 preg = calloc(1, sizeof(regex_t));
1390 if (!preg) {
1391 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1392 err_code = ERR_ALERT | ERR_FATAL;
1393 goto err;
1394 }
1395
1396 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1397 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001402 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001403 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001404 if (repl && err) {
1405 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1406 file, line, cmd, *err);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto err;
1409 }
1410
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001411 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001412 err_code |= ERR_WARN;
1413
Willy Tarreauf4068b62012-05-08 17:37:49 +02001414 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001415 return err_code;
1416 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001417 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 free(preg);
1419 return err_code;
1420}
1421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001424 * Returns the error code, 0 if OK, or any combination of :
1425 * - ERR_ABORT: must abort ASAP
1426 * - ERR_FATAL: we can continue parsing but not start the service
1427 * - ERR_WARN: a warning has been emitted
1428 * - ERR_ALERT: an alert has been emitted
1429 * Only the two first ones can stop processing, the two others are just
1430 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001432int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1433{
1434 static struct peers *curpeers = NULL;
1435 struct peer *newpeer = NULL;
1436 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001437 struct bind_conf *bind_conf;
1438 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001439 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001440 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001441
1442 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001443 if (!*args[1]) {
1444 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 err = invalid_char(args[1]);
1450 if (err) {
1451 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1452 file, linenum, *err, args[0], args[1]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001454 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001455 }
1456
1457 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 */
1462 if (strcmp(curpeers->id, args[1]) == 0) {
1463 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1464 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1465 err_code |= ERR_WARN;
1466 }
1467 }
1468
1469 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
1473 }
1474
1475 curpeers->next = peers;
1476 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001477 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 curpeers->conf.line = linenum;
1479 curpeers->last_change = now.tv_sec;
1480 curpeers->id = strdup(args[1]);
1481 }
1482 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001483 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001484 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001485 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001486
1487 if (!*args[2]) {
1488 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1489 file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1497 file, linenum, *err, args[1]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1504 err_code |= ERR_ALERT | ERR_ABORT;
1505 goto out;
1506 }
1507
1508 /* the peers are linked backwards first */
1509 curpeers->count++;
1510 newpeer->next = curpeers->remote;
1511 curpeers->remote = newpeer;
1512 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001513 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001514 newpeer->conf.line = linenum;
1515
1516 newpeer->last_change = now.tv_sec;
1517 newpeer->id = strdup(args[1]);
1518
Willy Tarreau902636f2013-03-10 19:44:48 +01001519 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001520 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001525
1526 proto = protocol_by_family(sk->ss_family);
1527 if (!proto || !proto->connect) {
1528 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1529 file, linenum, args[0], args[1]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001533
1534 if (port1 != port2) {
1535 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1536 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540
Willy Tarreau2aa38802013-02-20 19:20:59 +01001541 if (!port1) {
1542 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1543 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001549 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001550 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001551 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001552
Emeric Brun32da3c42010-09-23 18:39:19 +02001553 if (strcmp(newpeer->id, localpeer) == 0) {
1554 /* Current is local peer, it define a frontend */
1555 newpeer->local = 1;
1556
1557 if (!curpeers->peers_fe) {
1558 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001563
Willy Tarreau237250c2011-07-29 01:49:03 +02001564 init_new_proxy(curpeers->peers_fe);
1565 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001566
1567 curpeers->peers_fe->last_change = now.tv_sec;
1568 curpeers->peers_fe->id = strdup(args[1]);
1569 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001570 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001571 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1572 curpeers->peers_fe->timeout.connect = 5000;
1573 curpeers->peers_fe->accept = peer_accept;
1574 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001575 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1576 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001577
1578 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1579
Willy Tarreau902636f2013-03-10 19:44:48 +01001580 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1581 if (errmsg && *errmsg) {
1582 indent_msg(&errmsg, 2);
1583 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001584 }
1585 else
1586 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1587 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 err_code |= ERR_FATAL;
1589 goto out;
1590 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001591
1592 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1593 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1594 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1595 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1596 l->accept = session_accept;
1597 l->handler = process_session;
1598 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1599 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1600 global.maxsock += l->maxconn;
1601 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001603 else {
1604 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1605 file, linenum, args[0], args[1],
1606 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1607 err_code |= ERR_FATAL;
1608 goto out;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
1611 } /* neither "peer" nor "peers" */
1612 else if (*args[0] != 0) {
1613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617
1618out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001619 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001620 return err_code;
1621}
1622
Simon Horman69d29f92013-02-23 15:14:19 +09001623static int init_check(struct check *check, int type, const char * file, int linenum)
1624{
1625 check->type = type;
1626
1627 /* Allocate buffer for requests... */
1628 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1629 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1630 return ERR_ALERT | ERR_ABORT;
1631 }
1632 check->bi->size = global.tune.chksize;
1633
1634 /* Allocate buffer for responses... */
1635 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1636 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1637 return ERR_ALERT | ERR_ABORT;
1638 }
1639 check->bo->size = global.tune.chksize;
1640
1641 /* Allocate buffer for partial results... */
1642 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1643 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1644 return ERR_ALERT | ERR_ABORT;
1645 }
1646
1647 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1648
1649 return 0;
1650}
Emeric Brun32da3c42010-09-23 18:39:19 +02001651
Willy Tarreau3842f002009-06-14 11:39:52 +02001652int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653{
1654 static struct proxy *curproxy = NULL;
1655 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001656 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001657 int rc;
1658 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001659 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001660 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001661 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001662 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001663 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664
Willy Tarreau977b8e42006-12-29 14:19:17 +01001665 if (!strcmp(args[0], "listen"))
1666 rc = PR_CAP_LISTEN;
1667 else if (!strcmp(args[0], "frontend"))
1668 rc = PR_CAP_FE | PR_CAP_RS;
1669 else if (!strcmp(args[0], "backend"))
1670 rc = PR_CAP_BE | PR_CAP_RS;
1671 else if (!strcmp(args[0], "ruleset"))
1672 rc = PR_CAP_RS;
1673 else
1674 rc = PR_CAP_NONE;
1675
1676 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 if (!*args[1]) {
1678 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1679 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1680 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_ALERT | ERR_ABORT;
1682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001684
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001685 err = invalid_char(args[1]);
1686 if (err) {
1687 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1688 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001689 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001690 }
1691
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001692 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1693 /*
1694 * If there are two proxies with the same name only following
1695 * combinations are allowed:
1696 *
1697 * listen backend frontend ruleset
1698 * listen - - - -
1699 * backend - - OK -
1700 * frontend - OK - -
1701 * ruleset - - - -
1702 */
1703
1704 if (!strcmp(curproxy->id, args[1]) &&
1705 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1706 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001707 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1708 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1709 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001711 }
1712 }
1713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1715 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_ALERT | ERR_ABORT;
1717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001719
Willy Tarreau97cb7802010-01-03 20:23:58 +01001720 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 curproxy->next = proxy;
1722 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001723 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1724 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001725 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001727 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728
1729 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001730 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001731 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001732
Willy Tarreau4348fad2012-09-20 16:48:07 +02001733 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1734
Willy Tarreau902636f2013-03-10 19:44:48 +01001735 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1736 if (errmsg && *errmsg) {
1737 indent_msg(&errmsg, 2);
1738 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001739 }
1740 else
1741 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1742 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001743 err_code |= ERR_FATAL;
1744 goto out;
1745 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001746
Willy Tarreau4348fad2012-09-20 16:48:07 +02001747 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001748 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001750 }
1751
1752 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001753 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001754 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001755
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001758 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001759 curproxy->no_options = defproxy.no_options;
1760 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001761 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001762 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001763 curproxy->except_net = defproxy.except_net;
1764 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001765 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001766 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001768 if (defproxy.fwdfor_hdr_len) {
1769 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1770 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1771 }
1772
Willy Tarreaub86db342009-11-30 11:50:16 +01001773 if (defproxy.orgto_hdr_len) {
1774 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1775 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1776 }
1777
Mark Lamourinec2247f02012-01-04 13:02:01 -05001778 if (defproxy.server_id_hdr_len) {
1779 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1780 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1781 }
1782
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783 if (curproxy->cap & PR_CAP_FE) {
1784 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001785 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001786 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787
1788 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001789 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1790 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791
1792 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794
Willy Tarreau977b8e42006-12-29 14:19:17 +01001795 if (curproxy->cap & PR_CAP_BE) {
1796 curproxy->fullconn = defproxy.fullconn;
1797 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001799 if (defproxy.check_req) {
1800 curproxy->check_req = calloc(1, defproxy.check_len);
1801 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1802 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001803 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001805 if (defproxy.expect_str) {
1806 curproxy->expect_str = strdup(defproxy.expect_str);
1807 if (defproxy.expect_regex) {
1808 /* note: this regex is known to be valid */
1809 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1810 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1811 }
1812 }
1813
Willy Tarreau67402132012-05-31 20:40:20 +02001814 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001815 if (defproxy.cookie_name)
1816 curproxy->cookie_name = strdup(defproxy.cookie_name);
1817 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001818 if (defproxy.cookie_domain)
1819 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001820
Willy Tarreau31936852010-10-06 16:59:56 +02001821 if (defproxy.cookie_maxidle)
1822 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1823
1824 if (defproxy.cookie_maxlife)
1825 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1826
Emeric Brun647caf12009-06-30 17:57:00 +02001827 if (defproxy.rdp_cookie_name)
1828 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1829 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1830
Willy Tarreau01732802007-11-01 22:48:15 +01001831 if (defproxy.url_param_name)
1832 curproxy->url_param_name = strdup(defproxy.url_param_name);
1833 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001834
Benoitaffb4812009-03-25 13:02:10 +01001835 if (defproxy.hh_name)
1836 curproxy->hh_name = strdup(defproxy.hh_name);
1837 curproxy->hh_len = defproxy.hh_len;
1838 curproxy->hh_match_domain = defproxy.hh_match_domain;
1839
Willy Tarreauef9a3602012-12-08 22:29:20 +01001840 if (defproxy.conn_src.iface_name)
1841 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1842 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001843 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001844#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001845 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001846#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001849 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001850 if (defproxy.capture_name)
1851 curproxy->capture_name = strdup(defproxy.capture_name);
1852 curproxy->capture_namelen = defproxy.capture_namelen;
1853 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855
Willy Tarreau977b8e42006-12-29 14:19:17 +01001856 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001857 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001858 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001859 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001860 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 curproxy->uri_auth = defproxy.uri_auth;
1862 curproxy->mon_net = defproxy.mon_net;
1863 curproxy->mon_mask = defproxy.mon_mask;
1864 if (defproxy.monitor_uri)
1865 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1866 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001867 if (defproxy.defbe.name)
1868 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001869
1870 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001871 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1872 if (curproxy->conf.logformat_string &&
1873 curproxy->conf.logformat_string != default_http_log_format &&
1874 curproxy->conf.logformat_string != default_tcp_log_format &&
1875 curproxy->conf.logformat_string != clf_http_log_format)
1876 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1877
1878 if (defproxy.conf.lfs_file) {
1879 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1880 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1881 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001882 }
1883
1884 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001885 curproxy->timeout.connect = defproxy.timeout.connect;
1886 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001887 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001888 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001889 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001890 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001891 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001892 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001893 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001894 }
1895
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001897
1898 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001899 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001900 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001901 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001902 LIST_INIT(&node->list);
1903 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1904 }
1905
Willy Tarreau62a61232013-04-12 18:13:46 +02001906 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1907 if (curproxy->conf.uniqueid_format_string)
1908 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1909
1910 if (defproxy.conf.uif_file) {
1911 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1912 curproxy->conf.uif_line = defproxy.conf.uif_line;
1913 }
William Lallemanda73203e2012-03-12 12:48:57 +01001914
1915 /* copy default header unique id */
1916 if (defproxy.header_unique_id)
1917 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1918
William Lallemand82fe75c2012-10-23 10:25:10 +02001919 /* default compression options */
1920 if (defproxy.comp != NULL) {
1921 curproxy->comp = calloc(1, sizeof(struct comp));
1922 curproxy->comp->algos = defproxy.comp->algos;
1923 curproxy->comp->types = defproxy.comp->types;
1924 }
1925
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001927 curproxy->conf.used_listener_id = EB_ROOT;
1928 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001929
Willy Tarreau93893792009-07-23 13:19:11 +02001930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
1932 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1933 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001934 /* FIXME-20070101: we should do this too at the end of the
1935 * config parsing to free all default values.
1936 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001937 free(defproxy.check_req);
1938 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001939 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001940 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001941 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001942 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001943 free(defproxy.capture_name);
1944 free(defproxy.monitor_uri);
1945 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001946 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001947 free(defproxy.fwdfor_hdr_name);
1948 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001949 free(defproxy.orgto_hdr_name);
1950 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001951 free(defproxy.server_id_hdr_name);
1952 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001953 free(defproxy.expect_str);
1954 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001955
Willy Tarreau62a61232013-04-12 18:13:46 +02001956 if (defproxy.conf.logformat_string != default_http_log_format &&
1957 defproxy.conf.logformat_string != default_tcp_log_format &&
1958 defproxy.conf.logformat_string != clf_http_log_format)
1959 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001960
Willy Tarreau62a61232013-04-12 18:13:46 +02001961 free(defproxy.conf.uniqueid_format_string);
1962 free(defproxy.conf.lfs_file);
1963 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001964
Willy Tarreaua534fea2008-08-03 12:19:50 +02001965 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001966 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001967
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968 /* we cannot free uri_auth because it might already be used */
1969 init_default_instance();
1970 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001971 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1972 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001973 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 }
1976 else if (curproxy == NULL) {
1977 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001981
1982 /* update the current file and line being parsed */
1983 curproxy->conf.args.file = curproxy->conf.file;
1984 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001985
1986 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001988 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001989 int cur_arg;
1990
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 if (curproxy == &defproxy) {
1992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001997 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998
Willy Tarreau24709282013-03-10 21:32:12 +01001999 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002000 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002005
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002006 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002007
2008 /* use default settings for unix sockets */
2009 bind_conf->ux.uid = global.unix_bind.ux.uid;
2010 bind_conf->ux.gid = global.unix_bind.ux.gid;
2011 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002012
2013 /* NOTE: the following line might create several listeners if there
2014 * are comma-separated IPs or port ranges. So all further processing
2015 * will have to be applied to all listeners created after last_listen.
2016 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002017 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2018 if (errmsg && *errmsg) {
2019 indent_msg(&errmsg, 2);
2020 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002021 }
2022 else
2023 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2024 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002025 err_code |= ERR_ALERT | ERR_FATAL;
2026 goto out;
2027 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002028
Willy Tarreau4348fad2012-09-20 16:48:07 +02002029 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2030 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002031 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002032 }
2033
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002034 cur_arg = 2;
2035 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002036 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002037 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002038 char *err;
2039
Willy Tarreau26982662012-09-12 23:17:10 +02002040 kw = bind_find_kw(args[cur_arg]);
2041 if (kw) {
2042 char *err = NULL;
2043 int code;
2044
2045 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002046 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2047 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002048 cur_arg += 1 + kw->skip ;
2049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
2051 }
2052
Willy Tarreau4348fad2012-09-20 16:48:07 +02002053 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002054 err_code |= code;
2055
2056 if (code) {
2057 if (err && *err) {
2058 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002059 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002060 }
2061 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002062 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2063 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002064 if (code & ERR_FATAL) {
2065 free(err);
2066 cur_arg += 1 + kw->skip;
2067 goto out;
2068 }
2069 }
2070 free(err);
2071 cur_arg += 1 + kw->skip;
2072 continue;
2073 }
2074
Willy Tarreau8638f482012-09-18 18:01:17 +02002075 err = NULL;
2076 if (!bind_dumped) {
2077 bind_dump_kws(&err);
2078 indent_msg(&err, 4);
2079 bind_dumped = 1;
2080 }
2081
2082 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2083 file, linenum, args[0], args[1], args[cur_arg],
2084 err ? " Registered keywords :" : "", err ? err : "");
2085 free(err);
2086
Willy Tarreau93893792009-07-23 13:19:11 +02002087 err_code |= ERR_ALERT | ERR_FATAL;
2088 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002089 }
Willy Tarreau93893792009-07-23 13:19:11 +02002090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 }
2092 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2093 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2094 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002099 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 /* flush useless bits */
2103 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002106 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109
Willy Tarreau1c47f852006-07-09 08:22:27 +02002110 if (!*args[1]) {
2111 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2112 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002115 }
2116
Willy Tarreaua534fea2008-08-03 12:19:50 +02002117 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002118 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002119 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002120 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002121 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2122
Willy Tarreau93893792009-07-23 13:19:11 +02002123 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2126 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2127 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2128 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2129 else {
2130 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 }
2134 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002135 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002136 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002137
2138 if (curproxy == &defproxy) {
2139 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002143 }
2144
2145 if (!*args[1]) {
2146 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2147 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002150 }
2151
2152 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002153 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002154
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002155 if (curproxy->uuid <= 0) {
2156 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002157 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002160 }
2161
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002162 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2163 if (node) {
2164 struct proxy *target = container_of(node, struct proxy, conf.id);
2165 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2166 file, linenum, proxy_type_str(curproxy), curproxy->id,
2167 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
2171 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002172 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002173 else if (!strcmp(args[0], "description")) {
2174 int i, len=0;
2175 char *d;
2176
Cyril Bonté99ed3272010-01-24 23:29:44 +01002177 if (curproxy == &defproxy) {
2178 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2179 file, linenum, args[0]);
2180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
2182 }
2183
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002184 if (!*args[1]) {
2185 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2186 file, linenum, args[0]);
2187 return -1;
2188 }
2189
2190 for(i=1; *args[i]; i++)
2191 len += strlen(args[i])+1;
2192
2193 d = (char *)calloc(1, len);
2194 curproxy->desc = d;
2195
2196 d += sprintf(d, "%s", args[1]);
2197 for(i=2; *args[i]; i++)
2198 d += sprintf(d, " %s", args[i]);
2199
2200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2202 curproxy->state = PR_STSTOPPED;
2203 }
2204 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2205 curproxy->state = PR_STNEW;
2206 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002207 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2208 int cur_arg = 1;
2209 unsigned int set = 0;
2210
2211 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002212 unsigned int low, high;
2213
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002214 if (strcmp(args[cur_arg], "all") == 0) {
2215 set = 0;
2216 break;
2217 }
2218 else if (strcmp(args[cur_arg], "odd") == 0) {
2219 set |= 0x55555555;
2220 }
2221 else if (strcmp(args[cur_arg], "even") == 0) {
2222 set |= 0xAAAAAAAA;
2223 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002224 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002225 char *dash = strchr(args[cur_arg], '-');
2226
2227 low = high = str2uic(args[cur_arg]);
2228 if (dash)
2229 high = str2uic(dash + 1);
2230
2231 if (high < low) {
2232 unsigned int swap = low;
2233 low = high;
2234 high = swap;
2235 }
2236
2237 if (low < 1 || high > 32) {
2238 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002239 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002242 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002243
2244 if (high > global.nbproc) {
2245 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2246 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002247 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002248 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002249 while (low <= high)
2250 set |= 1 << (low++ - 1);
2251 }
2252 else {
2253 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2254 file, linenum, args[0]);
2255 err_code |= ERR_ALERT | ERR_FATAL;
2256 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002257 }
2258 cur_arg++;
2259 }
2260 curproxy->bind_proc = set;
2261 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002262 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002263 if (curproxy == &defproxy) {
2264 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002267 }
2268
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002269 err = invalid_char(args[1]);
2270 if (err) {
2271 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2272 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002274 }
2275
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002276 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002277 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2278 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002281 }
2282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2284 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285
Willy Tarreau977b8e42006-12-29 14:19:17 +01002286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002287 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002288
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 if (*(args[1]) == 0) {
2290 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2291 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002295
Willy Tarreau67402132012-05-31 20:40:20 +02002296 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002297 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002298 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002299 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 curproxy->cookie_name = strdup(args[1]);
2301 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002302
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 cur_arg = 2;
2304 while (*(args[cur_arg])) {
2305 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002306 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307 }
2308 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002309 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 }
2311 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002312 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
2314 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002315 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
2317 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002318 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002320 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002321 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002324 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002326 else if (!strcmp(args[cur_arg], "httponly")) {
2327 curproxy->ck_opts |= PR_CK_HTTPONLY;
2328 }
2329 else if (!strcmp(args[cur_arg], "secure")) {
2330 curproxy->ck_opts |= PR_CK_SECURE;
2331 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002332 else if (!strcmp(args[cur_arg], "domain")) {
2333 if (!*args[cur_arg + 1]) {
2334 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2335 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002338 }
2339
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002340 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002341 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002342 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2343 " dots nor does not start with a dot."
2344 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002345 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002346 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002347 }
2348
2349 err = invalid_domainchar(args[cur_arg + 1]);
2350 if (err) {
2351 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2352 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002355 }
2356
Willy Tarreau68a897b2009-12-03 23:28:34 +01002357 if (!curproxy->cookie_domain) {
2358 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2359 } else {
2360 /* one domain was already specified, add another one by
2361 * building the string which will be returned along with
2362 * the cookie.
2363 */
2364 char *new_ptr;
2365 int new_len = strlen(curproxy->cookie_domain) +
2366 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2367 new_ptr = malloc(new_len);
2368 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2369 free(curproxy->cookie_domain);
2370 curproxy->cookie_domain = new_ptr;
2371 }
Willy Tarreau31936852010-10-06 16:59:56 +02002372 cur_arg++;
2373 }
2374 else if (!strcmp(args[cur_arg], "maxidle")) {
2375 unsigned int maxidle;
2376 const char *res;
2377
2378 if (!*args[cur_arg + 1]) {
2379 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2380 file, linenum, args[cur_arg]);
2381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
2383 }
2384
2385 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2386 if (res) {
2387 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2388 file, linenum, *res, args[cur_arg]);
2389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
2391 }
2392 curproxy->cookie_maxidle = maxidle;
2393 cur_arg++;
2394 }
2395 else if (!strcmp(args[cur_arg], "maxlife")) {
2396 unsigned int maxlife;
2397 const char *res;
2398
2399 if (!*args[cur_arg + 1]) {
2400 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2401 file, linenum, args[cur_arg]);
2402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
2404 }
2405
2406 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2407 if (res) {
2408 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2409 file, linenum, *res, args[cur_arg]);
2410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
2412 }
2413 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002414 cur_arg++;
2415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002417 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 +02002418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422 cur_arg++;
2423 }
Willy Tarreau67402132012-05-31 20:40:20 +02002424 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2426 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
2429
Willy Tarreau67402132012-05-31 20:40:20 +02002430 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' 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 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002435
Willy Tarreau67402132012-05-31 20:40:20 +02002436 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002437 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2438 file, linenum);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002442 else if (!strcmp(args[0], "persist")) { /* persist */
2443 if (*(args[1]) == 0) {
2444 Alert("parsing [%s:%d] : missing persist method.\n",
2445 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002448 }
2449
2450 if (!strncmp(args[1], "rdp-cookie", 10)) {
2451 curproxy->options2 |= PR_O2_RDPC_PRST;
2452
Emeric Brunb982a3d2010-01-04 15:45:53 +01002453 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002454 const char *beg, *end;
2455
2456 beg = args[1] + 11;
2457 end = strchr(beg, ')');
2458
2459 if (!end || end == beg) {
2460 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2461 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002464 }
2465
2466 free(curproxy->rdp_cookie_name);
2467 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2468 curproxy->rdp_cookie_len = end-beg;
2469 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002470 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002471 free(curproxy->rdp_cookie_name);
2472 curproxy->rdp_cookie_name = strdup("msts");
2473 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2474 }
2475 else { /* syntax */
2476 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2477 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002480 }
2481 }
2482 else {
2483 Alert("parsing [%s:%d] : unknown persist method.\n",
2484 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002487 }
2488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002490 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002492 if (curproxy == &defproxy) {
2493 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002500
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002502 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002506 }
2507 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002508 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 curproxy->appsession_name = strdup(args[1]);
2510 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2511 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002512 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2513 if (err) {
2514 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2515 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002518 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002519 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002520
Willy Tarreau51041c72007-09-09 21:56:53 +02002521 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2522 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_ABORT;
2524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002526
2527 cur_arg = 6;
2528 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002529 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2530 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002531 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002532 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002533 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002534 } else if (!strcmp(args[cur_arg], "prefix")) {
2535 curproxy->options2 |= PR_O2_AS_PFX;
2536 } else if (!strcmp(args[cur_arg], "mode")) {
2537 if (!*args[cur_arg + 1]) {
2538 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2539 file, linenum, args[0], args[cur_arg]);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
2542 }
2543
2544 cur_arg++;
2545 if (!strcmp(args[cur_arg], "query-string")) {
2546 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2547 curproxy->options2 |= PR_O2_AS_M_QS;
2548 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2549 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2550 curproxy->options2 |= PR_O2_AS_M_PP;
2551 } else {
2552 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
2555 }
2556 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002557 cur_arg++;
2558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 } /* Url App Session */
2560 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002561 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002565 if (curproxy == &defproxy) {
2566 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
2569 }
2570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (*(args[4]) == 0) {
2572 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002577 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 curproxy->capture_name = strdup(args[2]);
2579 curproxy->capture_namelen = strlen(curproxy->capture_name);
2580 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 curproxy->to_log |= LW_COOKIE;
2582 }
2583 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2584 struct cap_hdr *hdr;
2585
2586 if (curproxy == &defproxy) {
2587 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 +02002588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
2591
2592 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2593 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2594 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
2598
2599 hdr = calloc(sizeof(struct cap_hdr), 1);
2600 hdr->next = curproxy->req_cap;
2601 hdr->name = strdup(args[3]);
2602 hdr->namelen = strlen(args[3]);
2603 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002604 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 hdr->index = curproxy->nb_req_cap++;
2606 curproxy->req_cap = hdr;
2607 curproxy->to_log |= LW_REQHDR;
2608 }
2609 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2610 struct cap_hdr *hdr;
2611
2612 if (curproxy == &defproxy) {
2613 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 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 }
2617
2618 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2619 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2620 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 }
2624 hdr = calloc(sizeof(struct cap_hdr), 1);
2625 hdr->next = curproxy->rsp_cap;
2626 hdr->name = strdup(args[3]);
2627 hdr->namelen = strlen(args[3]);
2628 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002629 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 hdr->index = curproxy->nb_rsp_cap++;
2631 curproxy->rsp_cap = hdr;
2632 curproxy->to_log |= LW_RSPHDR;
2633 }
2634 else {
2635 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 }
2640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002642 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002644
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 if (*(args[1]) == 0) {
2646 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 }
2651 curproxy->conn_retries = atol(args[1]);
2652 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002653 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002654 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002655
2656 if (curproxy == &defproxy) {
2657 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661
Willy Tarreau20b0de52012-12-24 15:45:22 +01002662 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2663 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2664 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2665 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002666 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002667 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2668 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 +01002669 file, linenum, args[0]);
2670 err_code |= ERR_WARN;
2671 }
2672
Willy Tarreauff011f22011-01-06 17:51:27 +01002673 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002674
Willy Tarreauff011f22011-01-06 17:51:27 +01002675 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002676 err_code |= ERR_ALERT | ERR_ABORT;
2677 goto out;
2678 }
2679
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002680 err_code |= warnif_cond_conflicts(rule->cond,
2681 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2682 file, linenum);
2683
Willy Tarreauff011f22011-01-06 17:51:27 +01002684 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002685 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002686 else if (!strcmp(args[0], "http-response")) { /* response access control */
2687 struct http_res_rule *rule;
2688
2689 if (curproxy == &defproxy) {
2690 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
2693 }
2694
2695 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2696 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2697 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2698 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2699 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2700 file, linenum, args[0]);
2701 err_code |= ERR_WARN;
2702 }
2703
2704 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2705
2706 if (!rule) {
2707 err_code |= ERR_ALERT | ERR_ABORT;
2708 goto out;
2709 }
2710
2711 err_code |= warnif_cond_conflicts(rule->cond,
2712 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2713 file, linenum);
2714
2715 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2716 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002717 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2718 /* set the header name and length into the proxy structure */
2719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2720 err_code |= ERR_WARN;
2721
2722 if (!*args[1]) {
2723 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2724 file, linenum, args[0]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728
2729 /* set the desired header name */
2730 free(curproxy->server_id_hdr_name);
2731 curproxy->server_id_hdr_name = strdup(args[1]);
2732 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2733 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002734 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002735 if (curproxy == &defproxy) {
2736 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002739 }
2740
Willy Tarreauef6494c2010-01-28 17:12:36 +01002741 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002742 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002746 }
2747
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002748 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2749 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2750 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002753 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002754
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002755 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002756 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002757 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002758 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002759 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002760
Cyril Bonté99ed3272010-01-24 23:29:44 +01002761 if (curproxy == &defproxy) {
2762 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
2766
Willy Tarreau4baae242012-12-27 12:00:31 +01002767 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2768 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2769 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002772 }
2773
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002774 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002775 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002776 err_code |= warnif_cond_conflicts(rule->cond,
2777 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2778 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002779 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002780 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002781 struct switching_rule *rule;
2782
Willy Tarreaub099aca2008-10-12 17:26:37 +02002783 if (curproxy == &defproxy) {
2784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002787 }
2788
Willy Tarreau55ea7572007-06-17 19:56:27 +02002789 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002791
2792 if (*(args[1]) == 0) {
2793 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002796 }
2797
Willy Tarreauef6494c2010-01-28 17:12:36 +01002798 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002799 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2800 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002803 }
2804
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002805 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2806 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2807 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002810 }
2811
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002812 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002813
Willy Tarreau55ea7572007-06-17 19:56:27 +02002814 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2815 rule->cond = cond;
2816 rule->be.name = strdup(args[1]);
2817 LIST_INIT(&rule->list);
2818 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2819 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002820 else if (strcmp(args[0], "use-server") == 0) {
2821 struct server_rule *rule;
2822
2823 if (curproxy == &defproxy) {
2824 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
2827 }
2828
2829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2830 err_code |= ERR_WARN;
2831
2832 if (*(args[1]) == 0) {
2833 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837
2838 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2839 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2840 file, linenum, args[0]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002845 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2846 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2847 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002852 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002853
2854 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2855 rule->cond = cond;
2856 rule->srv.name = strdup(args[1]);
2857 LIST_INIT(&rule->list);
2858 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2859 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2860 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002861 else if ((!strcmp(args[0], "force-persist")) ||
2862 (!strcmp(args[0], "ignore-persist"))) {
2863 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002864
2865 if (curproxy == &defproxy) {
2866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870
2871 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2872 err_code |= ERR_WARN;
2873
Willy Tarreauef6494c2010-01-28 17:12:36 +01002874 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002875 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2876 file, linenum, args[0]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002881 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2882 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2883 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002888 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2889 * where force-persist is applied.
2890 */
2891 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002892
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002893 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002894 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002895 if (!strcmp(args[0], "force-persist")) {
2896 rule->type = PERSIST_TYPE_FORCE;
2897 } else {
2898 rule->type = PERSIST_TYPE_IGNORE;
2899 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002900 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002901 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002902 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002903 else if (!strcmp(args[0], "stick-table")) {
2904 int myidx = 1;
2905
Emeric Brun32da3c42010-09-23 18:39:19 +02002906 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002907 curproxy->table.type = (unsigned int)-1;
2908 while (*args[myidx]) {
2909 const char *err;
2910
2911 if (strcmp(args[myidx], "size") == 0) {
2912 myidx++;
2913 if (!*(args[myidx])) {
2914 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2915 file, linenum, args[myidx-1]);
2916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2920 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2921 file, linenum, *err, args[myidx-1]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002925 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002926 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002927 else if (strcmp(args[myidx], "peers") == 0) {
2928 myidx++;
2929 if (!*(args[myidx])) {
2930 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2931 file, linenum, args[myidx-1]);
2932 err_code |= ERR_ALERT | ERR_FATAL;
2933 goto out;
2934 }
2935 curproxy->table.peers.name = strdup(args[myidx++]);
2936 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002937 else if (strcmp(args[myidx], "expire") == 0) {
2938 myidx++;
2939 if (!*(args[myidx])) {
2940 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2941 file, linenum, args[myidx-1]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2946 if (err) {
2947 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2948 file, linenum, *err, args[myidx-1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002953 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002954 }
2955 else if (strcmp(args[myidx], "nopurge") == 0) {
2956 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002957 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002958 }
2959 else if (strcmp(args[myidx], "type") == 0) {
2960 myidx++;
2961 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2962 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2963 file, linenum, args[myidx]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002967 /* myidx already points to next arg */
2968 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002969 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002970 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002971 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002972
2973 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002974 nw = args[myidx];
2975 while (*nw) {
2976 /* the "store" keyword supports a comma-separated list */
2977 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002978 sa = NULL; /* store arg */
2979 while (*nw && *nw != ',') {
2980 if (*nw == '(') {
2981 *nw = 0;
2982 sa = ++nw;
2983 while (*nw != ')') {
2984 if (!*nw) {
2985 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2986 file, linenum, args[0], cw);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990 nw++;
2991 }
2992 *nw = '\0';
2993 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002994 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002995 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002996 if (*nw)
2997 *nw++ = '\0';
2998 type = stktable_get_data_type(cw);
2999 if (type < 0) {
3000 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3001 file, linenum, args[0], cw);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
Willy Tarreauac782882010-06-20 10:41:54 +02003005
3006 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3007 switch (err) {
3008 case PE_NONE: break;
3009 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003010 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3011 file, linenum, args[0], cw);
3012 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003013 break;
3014
3015 case PE_ARG_MISSING:
3016 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3017 file, linenum, args[0], cw);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020
3021 case PE_ARG_NOT_USED:
3022 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3023 file, linenum, args[0], cw);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026
3027 default:
3028 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3029 file, linenum, args[0], cw);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003032 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003033 }
3034 myidx++;
3035 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003036 else {
3037 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3038 file, linenum, args[myidx]);
3039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003041 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003042 }
3043
3044 if (!curproxy->table.size) {
3045 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3046 file, linenum);
3047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
3049 }
3050
3051 if (curproxy->table.type == (unsigned int)-1) {
3052 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3053 file, linenum);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
3057 }
3058 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003060 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003061 int myidx = 0;
3062 const char *name = NULL;
3063 int flags;
3064
3065 if (curproxy == &defproxy) {
3066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
3070
3071 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3072 err_code |= ERR_WARN;
3073 goto out;
3074 }
3075
3076 myidx++;
3077 if ((strcmp(args[myidx], "store") == 0) ||
3078 (strcmp(args[myidx], "store-request") == 0)) {
3079 myidx++;
3080 flags = STK_IS_STORE;
3081 }
3082 else if (strcmp(args[myidx], "store-response") == 0) {
3083 myidx++;
3084 flags = STK_IS_STORE | STK_ON_RSP;
3085 }
3086 else if (strcmp(args[myidx], "match") == 0) {
3087 myidx++;
3088 flags = STK_IS_MATCH;
3089 }
3090 else if (strcmp(args[myidx], "on") == 0) {
3091 myidx++;
3092 flags = STK_IS_MATCH | STK_IS_STORE;
3093 }
3094 else {
3095 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
3099
3100 if (*(args[myidx]) == 0) {
3101 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003106 curproxy->conf.args.ctx = ARGC_STK;
3107 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003108 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003109 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113
3114 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003115 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3116 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3117 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003118 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003119 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003120 goto out;
3121 }
3122 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003123 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3124 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3125 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003127 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003128 goto out;
3129 }
3130 }
3131
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003132 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003133 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003134
Emeric Brunb982a3d2010-01-04 15:45:53 +01003135 if (strcmp(args[myidx], "table") == 0) {
3136 myidx++;
3137 name = args[myidx++];
3138 }
3139
Willy Tarreauef6494c2010-01-28 17:12:36 +01003140 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003141 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3142 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3143 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003144 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003145 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003146 goto out;
3147 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003148 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003149 else if (*(args[myidx])) {
3150 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3151 file, linenum, args[0], args[myidx]);
3152 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003153 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003154 goto out;
3155 }
Emeric Brun97679e72010-09-23 17:56:44 +02003156 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003157 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003158 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003159 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003160
Emeric Brunb982a3d2010-01-04 15:45:53 +01003161 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3162 rule->cond = cond;
3163 rule->expr = expr;
3164 rule->flags = flags;
3165 rule->table.name = name ? strdup(name) : NULL;
3166 LIST_INIT(&rule->list);
3167 if (flags & STK_ON_RSP)
3168 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3169 else
3170 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003173 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003175
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3177 curproxy->uri_auth = NULL; /* we must detach from the default config */
3178
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003179 if (!*args[1]) {
3180 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003181 } else if (!strcmp(args[1], "admin")) {
3182 struct stats_admin_rule *rule;
3183
3184 if (curproxy == &defproxy) {
3185 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
3188 }
3189
3190 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3191 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3192 err_code |= ERR_ALERT | ERR_ABORT;
3193 goto out;
3194 }
3195
3196 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3197 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3198 file, linenum, args[0], args[1]);
3199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
3201 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003202 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3203 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3204 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
3207 }
3208
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003209 err_code |= warnif_cond_conflicts(cond,
3210 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3211 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003212
3213 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3214 rule->cond = cond;
3215 LIST_INIT(&rule->list);
3216 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 } else if (!strcmp(args[1], "uri")) {
3218 if (*(args[2]) == 0) {
3219 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_ABORT;
3225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
3227 } else if (!strcmp(args[1], "realm")) {
3228 if (*(args[2]) == 0) {
3229 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3233 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_ABORT;
3235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003237 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003238 unsigned interval;
3239
3240 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3241 if (err) {
3242 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3243 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003246 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3247 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_ALERT | ERR_ABORT;
3249 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003250 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003251 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003252 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003253
3254 if (curproxy == &defproxy) {
3255 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
3258 }
3259
3260 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3261 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3262 err_code |= ERR_ALERT | ERR_ABORT;
3263 goto out;
3264 }
3265
Willy Tarreauff011f22011-01-06 17:51:27 +01003266 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3267 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003268 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3269 file, linenum, args[0]);
3270 err_code |= ERR_WARN;
3271 }
3272
Willy Tarreauff011f22011-01-06 17:51:27 +01003273 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003274
Willy Tarreauff011f22011-01-06 17:51:27 +01003275 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003276 err_code |= ERR_ALERT | ERR_ABORT;
3277 goto out;
3278 }
3279
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003280 err_code |= warnif_cond_conflicts(rule->cond,
3281 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3282 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003283 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003284
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 } else if (!strcmp(args[1], "auth")) {
3286 if (*(args[2]) == 0) {
3287 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3291 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
3295 } else if (!strcmp(args[1], "scope")) {
3296 if (*(args[2]) == 0) {
3297 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_ALERT | ERR_ABORT;
3303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
3305 } else if (!strcmp(args[1], "enable")) {
3306 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003311 } else if (!strcmp(args[1], "hide-version")) {
3312 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
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;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003316 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003317 } else if (!strcmp(args[1], "show-legends")) {
3318 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3319 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3320 err_code |= ERR_ALERT | ERR_ABORT;
3321 goto out;
3322 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003323 } else if (!strcmp(args[1], "show-node")) {
3324
3325 if (*args[2]) {
3326 int i;
3327 char c;
3328
3329 for (i=0; args[2][i]; i++) {
3330 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003331 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3332 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003333 break;
3334 }
3335
3336 if (!i || args[2][i]) {
3337 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3338 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3339 file, linenum, args[0], args[1]);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
3343 }
3344
3345 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3346 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3347 err_code |= ERR_ALERT | ERR_ABORT;
3348 goto out;
3349 }
3350 } else if (!strcmp(args[1], "show-desc")) {
3351 char *desc = NULL;
3352
3353 if (*args[2]) {
3354 int i, len=0;
3355 char *d;
3356
3357 for(i=2; *args[i]; i++)
3358 len += strlen(args[i])+1;
3359
3360 desc = d = (char *)calloc(1, len);
3361
3362 d += sprintf(d, "%s", args[2]);
3363 for(i=3; *args[i]; i++)
3364 d += sprintf(d, " %s", args[i]);
3365 }
3366
3367 if (!*args[2] && !global.desc)
3368 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3369 file, linenum, args[1]);
3370 else {
3371 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3372 free(desc);
3373 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3374 err_code |= ERR_ALERT | ERR_ABORT;
3375 goto out;
3376 }
3377 free(desc);
3378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003380stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003381 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 +01003382 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
3386 }
3387 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003388 int optnum;
3389
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003390 if (*(args[1]) == '\0') {
3391 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003396
3397 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3398 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003399 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3400 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3401 file, linenum, cfg_opts[optnum].name);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
Willy Tarreau93893792009-07-23 13:19:11 +02003405 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3406 err_code |= ERR_WARN;
3407 goto out;
3408 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003409
Willy Tarreau3842f002009-06-14 11:39:52 +02003410 curproxy->no_options &= ~cfg_opts[optnum].val;
3411 curproxy->options &= ~cfg_opts[optnum].val;
3412
3413 switch (kwm) {
3414 case KWM_STD:
3415 curproxy->options |= cfg_opts[optnum].val;
3416 break;
3417 case KWM_NO:
3418 curproxy->no_options |= cfg_opts[optnum].val;
3419 break;
3420 case KWM_DEF: /* already cleared */
3421 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003422 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003423
Willy Tarreau93893792009-07-23 13:19:11 +02003424 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003425 }
3426 }
3427
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003428 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3429 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003430 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3431 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3432 file, linenum, cfg_opts2[optnum].name);
3433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
3435 }
Willy Tarreau93893792009-07-23 13:19:11 +02003436 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3437 err_code |= ERR_WARN;
3438 goto out;
3439 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003440
Willy Tarreau3842f002009-06-14 11:39:52 +02003441 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3442 curproxy->options2 &= ~cfg_opts2[optnum].val;
3443
3444 switch (kwm) {
3445 case KWM_STD:
3446 curproxy->options2 |= cfg_opts2[optnum].val;
3447 break;
3448 case KWM_NO:
3449 curproxy->no_options2 |= cfg_opts2[optnum].val;
3450 break;
3451 case KWM_DEF: /* already cleared */
3452 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003453 }
Willy Tarreau93893792009-07-23 13:19:11 +02003454 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003455 }
3456 }
3457
Willy Tarreau3842f002009-06-14 11:39:52 +02003458 if (kwm != KWM_STD) {
3459 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003460 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003463 }
3464
Emeric Brun3a058f32009-06-30 18:26:00 +02003465 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003466 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003468 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003469 if (*(args[2]) != '\0') {
3470 if (!strcmp(args[2], "clf")) {
3471 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003472 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003473 } else {
3474 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003477 }
3478 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003479 if (curproxy->conf.logformat_string != default_http_log_format &&
3480 curproxy->conf.logformat_string != default_tcp_log_format &&
3481 curproxy->conf.logformat_string != clf_http_log_format)
3482 free(curproxy->conf.logformat_string);
3483 curproxy->conf.logformat_string = logformat;
3484
3485 free(curproxy->conf.lfs_file);
3486 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3487 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003488 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003489 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003491 if (curproxy->conf.logformat_string != default_http_log_format &&
3492 curproxy->conf.logformat_string != default_tcp_log_format &&
3493 curproxy->conf.logformat_string != clf_http_log_format)
3494 free(curproxy->conf.logformat_string);
3495 curproxy->conf.logformat_string = default_tcp_log_format;
3496
3497 free(curproxy->conf.lfs_file);
3498 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3499 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003501 else if (!strcmp(args[1], "tcpka")) {
3502 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003503 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003505
3506 if (curproxy->cap & PR_CAP_FE)
3507 curproxy->options |= PR_O_TCP_CLI_KA;
3508 if (curproxy->cap & PR_CAP_BE)
3509 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
3511 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_WARN;
3514
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003516 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003517 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003518 curproxy->options2 &= ~PR_O2_CHK_ANY;
3519 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 if (!*args[2]) { /* no argument */
3521 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3522 curproxy->check_len = strlen(DEF_CHECK_REQ);
3523 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003524 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 curproxy->check_req = (char *)malloc(reqlen);
3526 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003527 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003529 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 if (*args[4])
3531 reqlen += strlen(args[4]);
3532 else
3533 reqlen += strlen("HTTP/1.0");
3534
3535 curproxy->check_req = (char *)malloc(reqlen);
3536 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003537 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003539 }
3540 else if (!strcmp(args[1], "ssl-hello-chk")) {
3541 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003542 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003544
Willy Tarreaua534fea2008-08-03 12:19:50 +02003545 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003546 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003547 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003548 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 }
Willy Tarreau23677902007-05-08 23:50:35 +02003550 else if (!strcmp(args[1], "smtpchk")) {
3551 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003552 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003553 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003554 curproxy->options2 &= ~PR_O2_CHK_ANY;
3555 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003556
3557 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3558 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3559 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3560 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3561 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3562 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3563 curproxy->check_req = (char *)malloc(reqlen);
3564 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3565 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3566 } else {
3567 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3568 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3569 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3570 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3571 }
3572 }
3573 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003574 else if (!strcmp(args[1], "lb-agent-chk")) {
3575 /* use dynmaic health check */
3576 free(curproxy->check_req);
3577 curproxy->check_req = NULL;
3578 curproxy->options2 &= ~PR_O2_CHK_ANY;
3579 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3580 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003581 else if (!strcmp(args[1], "pgsql-check")) {
3582 /* use PostgreSQL request to check servers' health */
3583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3584 err_code |= ERR_WARN;
3585
3586 free(curproxy->check_req);
3587 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003588 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003589 curproxy->options2 |= PR_O2_PGSQL_CHK;
3590
3591 if (*(args[2])) {
3592 int cur_arg = 2;
3593
3594 while (*(args[cur_arg])) {
3595 if (strcmp(args[cur_arg], "user") == 0) {
3596 char * packet;
3597 uint32_t packet_len;
3598 uint32_t pv;
3599
3600 /* suboption header - needs additional argument for it */
3601 if (*(args[cur_arg+1]) == 0) {
3602 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3603 file, linenum, args[0], args[1], args[cur_arg]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607
3608 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3609 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3610 pv = htonl(0x30000); /* protocol version 3.0 */
3611
3612 packet = (char*) calloc(1, packet_len);
3613
3614 memcpy(packet + 4, &pv, 4);
3615
3616 /* copy "user" */
3617 memcpy(packet + 8, "user", 4);
3618
3619 /* copy username */
3620 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3621
3622 free(curproxy->check_req);
3623 curproxy->check_req = packet;
3624 curproxy->check_len = packet_len;
3625
3626 packet_len = htonl(packet_len);
3627 memcpy(packet, &packet_len, 4);
3628 cur_arg += 2;
3629 } else {
3630 /* unknown suboption - catchall */
3631 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3632 file, linenum, args[0], args[1]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 } /* end while loop */
3637 }
3638 }
3639
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003640 else if (!strcmp(args[1], "redis-check")) {
3641 /* use REDIS PING request to check servers' health */
3642 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3643 err_code |= ERR_WARN;
3644
3645 free(curproxy->check_req);
3646 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003647 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003648 curproxy->options2 |= PR_O2_REDIS_CHK;
3649
3650 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3651 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3652 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3653 }
3654
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003655 else if (!strcmp(args[1], "mysql-check")) {
3656 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3658 err_code |= ERR_WARN;
3659
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003660 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003661 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003662 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003663 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003664
3665 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3666 * const char mysql40_client_auth_pkt[] = {
3667 * "\x0e\x00\x00" // packet length
3668 * "\x01" // packet number
3669 * "\x00\x00" // client capabilities
3670 * "\x00\x00\x01" // max packet
3671 * "haproxy\x00" // username (null terminated string)
3672 * "\x00" // filler (always 0x00)
3673 * "\x01\x00\x00" // packet length
3674 * "\x00" // packet number
3675 * "\x01" // COM_QUIT command
3676 * };
3677 */
3678
3679 if (*(args[2])) {
3680 int cur_arg = 2;
3681
3682 while (*(args[cur_arg])) {
3683 if (strcmp(args[cur_arg], "user") == 0) {
3684 char *mysqluser;
3685 int packetlen, reqlen, userlen;
3686
3687 /* suboption header - needs additional argument for it */
3688 if (*(args[cur_arg+1]) == 0) {
3689 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3690 file, linenum, args[0], args[1], args[cur_arg]);
3691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
3693 }
3694 mysqluser = args[cur_arg + 1];
3695 userlen = strlen(mysqluser);
3696 packetlen = userlen + 7;
3697 reqlen = packetlen + 9;
3698
3699 free(curproxy->check_req);
3700 curproxy->check_req = (char *)calloc(1, reqlen);
3701 curproxy->check_len = reqlen;
3702
3703 snprintf(curproxy->check_req, 4, "%c%c%c",
3704 ((unsigned char) packetlen & 0xff),
3705 ((unsigned char) (packetlen >> 8) & 0xff),
3706 ((unsigned char) (packetlen >> 16) & 0xff));
3707
3708 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003709 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003710 curproxy->check_req[8] = 1;
3711 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3712 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3713 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3714 cur_arg += 2;
3715 } else {
3716 /* unknown suboption - catchall */
3717 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3718 file, linenum, args[0], args[1]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722 } /* end while loop */
3723 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003724 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003725 else if (!strcmp(args[1], "ldap-check")) {
3726 /* use LDAP request to check servers' health */
3727 free(curproxy->check_req);
3728 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003729 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003730 curproxy->options2 |= PR_O2_LDAP_CHK;
3731
3732 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3733 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3734 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3735 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003736 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003737 int cur_arg;
3738
3739 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3740 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003741 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003742
Willy Tarreau87cf5142011-08-19 22:57:24 +02003743 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003744
3745 free(curproxy->fwdfor_hdr_name);
3746 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3747 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3748
3749 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3750 cur_arg = 2;
3751 while (*(args[cur_arg])) {
3752 if (!strcmp(args[cur_arg], "except")) {
3753 /* suboption except - needs additional argument for it */
3754 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3755 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3756 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003759 }
3760 /* flush useless bits */
3761 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003762 cur_arg += 2;
3763 } else if (!strcmp(args[cur_arg], "header")) {
3764 /* suboption header - needs additional argument for it */
3765 if (*(args[cur_arg+1]) == 0) {
3766 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3767 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003770 }
3771 free(curproxy->fwdfor_hdr_name);
3772 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3773 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3774 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003775 } else if (!strcmp(args[cur_arg], "if-none")) {
3776 curproxy->options &= ~PR_O_FF_ALWAYS;
3777 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003778 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003779 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003780 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003781 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003784 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003785 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003786 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003787 else if (!strcmp(args[1], "originalto")) {
3788 int cur_arg;
3789
3790 /* insert x-original-to field, but not for the IP address listed as an except.
3791 * set default options (ie: bitfield, header name, etc)
3792 */
3793
3794 curproxy->options |= PR_O_ORGTO;
3795
3796 free(curproxy->orgto_hdr_name);
3797 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3798 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3799
Willy Tarreau87cf5142011-08-19 22:57:24 +02003800 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003801 cur_arg = 2;
3802 while (*(args[cur_arg])) {
3803 if (!strcmp(args[cur_arg], "except")) {
3804 /* suboption except - needs additional argument for it */
3805 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3806 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3807 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003810 }
3811 /* flush useless bits */
3812 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3813 cur_arg += 2;
3814 } else if (!strcmp(args[cur_arg], "header")) {
3815 /* suboption header - needs additional argument for it */
3816 if (*(args[cur_arg+1]) == 0) {
3817 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3818 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003821 }
3822 free(curproxy->orgto_hdr_name);
3823 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3824 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3825 cur_arg += 2;
3826 } else {
3827 /* unknown suboption - catchall */
3828 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3829 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003832 }
3833 } /* end while loop */
3834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 else {
3836 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 }
Willy Tarreau93893792009-07-23 13:19:11 +02003840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003842 else if (!strcmp(args[0], "default_backend")) {
3843 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003845
3846 if (*(args[1]) == 0) {
3847 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003850 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003851 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003852 curproxy->defbe.name = strdup(args[1]);
3853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003857
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003858 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 /* enable reconnections to dispatch */
3862 curproxy->options |= PR_O_REDISP;
3863 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003864 else if (!strcmp(args[0], "http-check")) {
3865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003867
3868 if (strcmp(args[1], "disable-on-404") == 0) {
3869 /* enable a graceful server shutdown on an HTTP 404 response */
3870 curproxy->options |= PR_O_DISABLE404;
3871 }
Willy Tarreauef781042010-01-27 11:53:01 +01003872 else if (strcmp(args[1], "send-state") == 0) {
3873 /* enable emission of the apparent state of a server in HTTP checks */
3874 curproxy->options2 |= PR_O2_CHK_SNDST;
3875 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003876 else if (strcmp(args[1], "expect") == 0) {
3877 const char *ptr_arg;
3878 int cur_arg;
3879
3880 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3881 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
3885
3886 cur_arg = 2;
3887 /* consider exclamation marks, sole or at the beginning of a word */
3888 while (*(ptr_arg = args[cur_arg])) {
3889 while (*ptr_arg == '!') {
3890 curproxy->options2 ^= PR_O2_EXP_INV;
3891 ptr_arg++;
3892 }
3893 if (*ptr_arg)
3894 break;
3895 cur_arg++;
3896 }
3897 /* now ptr_arg points to the beginning of a word past any possible
3898 * exclamation mark, and cur_arg is the argument which holds this word.
3899 */
3900 if (strcmp(ptr_arg, "status") == 0) {
3901 if (!*(args[cur_arg + 1])) {
3902 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3903 file, linenum, args[0], args[1], ptr_arg);
3904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003908 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003909 curproxy->expect_str = strdup(args[cur_arg + 1]);
3910 }
3911 else if (strcmp(ptr_arg, "string") == 0) {
3912 if (!*(args[cur_arg + 1])) {
3913 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3914 file, linenum, args[0], args[1], ptr_arg);
3915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
3917 }
3918 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003919 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003920 curproxy->expect_str = strdup(args[cur_arg + 1]);
3921 }
3922 else if (strcmp(ptr_arg, "rstatus") == 0) {
3923 if (!*(args[cur_arg + 1])) {
3924 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3925 file, linenum, args[0], args[1], ptr_arg);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003930 free(curproxy->expect_str);
3931 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3932 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003933 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3934 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3935 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3936 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
3939 }
3940 }
3941 else if (strcmp(ptr_arg, "rstring") == 0) {
3942 if (!*(args[cur_arg + 1])) {
3943 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3944 file, linenum, args[0], args[1], ptr_arg);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003949 free(curproxy->expect_str);
3950 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3951 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003952 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3953 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3954 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3955 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
3959 }
3960 else {
3961 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3962 file, linenum, args[0], args[1], ptr_arg);
3963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
3965 }
3966 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003967 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003968 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 +02003969 err_code |= ERR_ALERT | ERR_FATAL;
3970 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003971 }
3972 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003973 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003974 if (curproxy == &defproxy) {
3975 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003978 }
3979
Willy Tarreaub80c2302007-11-30 20:51:32 +01003980 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003982
3983 if (strcmp(args[1], "fail") == 0) {
3984 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003985 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003986 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3987 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003990 }
3991
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003992 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3993 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3994 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003997 }
3998 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3999 }
4000 else {
4001 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004004 }
4005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006#ifdef TPROXY
4007 else if (!strcmp(args[0], "transparent")) {
4008 /* enable transparent proxy connections */
4009 curproxy->options |= PR_O_TRANSP;
4010 }
4011#endif
4012 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004013 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004015
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 if (*(args[1]) == 0) {
4017 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020 }
4021 curproxy->maxconn = atol(args[1]);
4022 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004023 else if (!strcmp(args[0], "backlog")) { /* backlog */
4024 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004026
4027 if (*(args[1]) == 0) {
4028 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004031 }
4032 curproxy->backlog = atol(args[1]);
4033 }
Willy Tarreau86034312006-12-29 00:10:33 +01004034 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004037
Willy Tarreau86034312006-12-29 00:10:33 +01004038 if (*(args[1]) == 0) {
4039 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004042 }
4043 curproxy->fullconn = atol(args[1]);
4044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4046 if (*(args[1]) == 0) {
4047 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004051 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4052 if (err) {
4053 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4054 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004057 }
4058 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 }
4060 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004061 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004062 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004063 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004064
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 if (curproxy == &defproxy) {
4066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004070 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004072
Willy Tarreau902636f2013-03-10 19:44:48 +01004073 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004074 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004075 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004076 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004077 goto out;
4078 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004079
4080 proto = protocol_by_family(sk->ss_family);
4081 if (!proto || !proto->connect) {
4082 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4083 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087
4088 if (port1 != port2) {
4089 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4090 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004094
4095 if (!port1) {
4096 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4097 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
4100 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004101
Willy Tarreaud5191e72010-02-09 20:50:45 +01004102 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004103 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 }
4105 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004106 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004107 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004108
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004109 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4110 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004115 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004116 /**
4117 * The syntax for hash-type config element is
4118 * hash-type {map-based|consistent} [[<algo>] avalanche]
4119 *
4120 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4121 */
4122 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004123
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004124 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4125 err_code |= ERR_WARN;
4126
4127 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004128 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4129 }
4130 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004131 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4132 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004133 else if (strcmp(args[1], "avalanche") == 0) {
4134 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]);
4135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004137 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004138 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004139 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
Bhaskar98634f02013-10-29 23:30:51 -04004143
4144 /* set the hash function to use */
4145 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004146 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004147 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004148
4149 /* if consistent with no argument, then avalanche modifier is also applied */
4150 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4151 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004152 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004153 /* set the hash function */
4154 if (!strcmp(args[2], "sdbm")) {
4155 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4156 }
4157 else if (!strcmp(args[2], "djb2")) {
4158 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004159 } else if (!strcmp(args[2], "wt6")) {
4160 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004161 }
4162 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004163 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 -05004164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
4167
4168 /* set the hash modifier */
4169 if (!strcmp(args[3], "avalanche")) {
4170 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4171 }
4172 else if (*args[3]) {
4173 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
Bhaskar98634f02013-10-29 23:30:51 -04004177 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004178 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004179 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004181 short realport = 0;
4182 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004184 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004188 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004189 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004191
4192 if (!*args[2]) {
4193 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004198
4199 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004200 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004201 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4202 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004205 }
4206
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004207 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004208 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004209 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004210 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004211
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004212 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4213 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4214 err_code |= ERR_ALERT | ERR_ABORT;
4215 goto out;
4216 }
4217
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004218 /* the servers are linked backwards first */
4219 newsrv->next = curproxy->srv;
4220 curproxy->srv = newsrv;
4221 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004222 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004223 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004225 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004226 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004227 LIST_INIT(&newsrv->pendconns);
4228 do_check = 0;
4229 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 Horman66183002013-02-23 10:16:43 +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;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004287 newsrv->rise = curproxy->defsrv.rise;
4288 newsrv->fall = curproxy->defsrv.fall;
4289 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4290 newsrv->minconn = curproxy->defsrv.minconn;
4291 newsrv->maxconn = curproxy->defsrv.maxconn;
4292 newsrv->slowstart = curproxy->defsrv.slowstart;
4293 newsrv->onerror = curproxy->defsrv.onerror;
4294 newsrv->consecutive_errors_limit
4295 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004296#ifdef OPENSSL
4297 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4298#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004299 newsrv->uweight = newsrv->iweight
4300 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004302 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303
Simon Horman69d29f92013-02-23 15:14:19 +09004304 newsrv->check.status = HCHK_STATUS_INI;
4305 newsrv->check.server = newsrv;
4306
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004307 cur_arg = 3;
4308 } else {
4309 newsrv = &curproxy->defsrv;
4310 cur_arg = 1;
4311 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004312
Willy Tarreaubaaee002006-06-26 02:48:02 +02004313 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004314 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 newsrv->cookie = strdup(args[cur_arg + 1]);
4316 newsrv->cklen = strlen(args[cur_arg + 1]);
4317 cur_arg += 2;
4318 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004319 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004320 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4321 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4322 cur_arg += 2;
4323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004325 if (!*args[cur_arg + 1]) {
4326 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4327 file, linenum, args[cur_arg]);
4328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
4330 }
4331
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004333 if (newsrv->rise <= 0) {
4334 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4335 file, linenum, args[cur_arg]);
4336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
4338 }
4339
Willy Tarreau96839092010-03-29 10:02:24 +02004340 if (newsrv->health)
4341 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 cur_arg += 2;
4343 }
4344 else if (!strcmp(args[cur_arg], "fall")) {
4345 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004346
4347 if (!*args[cur_arg + 1]) {
4348 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4349 file, linenum, args[cur_arg]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353
4354 if (newsrv->fall <= 0) {
4355 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4356 file, linenum, args[cur_arg]);
4357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 cur_arg += 2;
4362 }
4363 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004364 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4365 if (err) {
4366 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4367 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004370 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004371 if (val <= 0) {
4372 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4373 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004376 }
Simon Horman66183002013-02-23 10:16:43 +09004377 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 cur_arg += 2;
4379 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004380 else if (!strcmp(args[cur_arg], "fastinter")) {
4381 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4382 if (err) {
4383 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4384 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004387 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004388 if (val <= 0) {
4389 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4390 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004393 }
Simon Horman66183002013-02-23 10:16:43 +09004394 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004395 cur_arg += 2;
4396 }
4397 else if (!strcmp(args[cur_arg], "downinter")) {
4398 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4399 if (err) {
4400 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4401 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004404 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004405 if (val <= 0) {
4406 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4407 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004410 }
Simon Horman66183002013-02-23 10:16:43 +09004411 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004412 cur_arg += 2;
4413 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004414 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004415 struct sockaddr_storage *sk;
4416 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004417 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004418
Willy Tarreau902636f2013-03-10 19:44:48 +01004419 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004420 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004421 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004422 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004423 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004424 goto out;
4425 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004426
4427 proto = protocol_by_family(sk->ss_family);
4428 if (!proto || !proto->connect) {
4429 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004430 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004434
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004435 if (port1 != port2) {
4436 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4437 file, linenum, args[cur_arg], args[cur_arg + 1]);
4438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
4440 }
4441
Simon Horman66183002013-02-23 10:16:43 +09004442 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004443 cur_arg += 2;
4444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004446 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 cur_arg += 2;
4448 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004449 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 newsrv->state |= SRV_BACKUP;
4451 cur_arg ++;
4452 }
Simon Hormanfa461682011-06-25 09:39:49 +09004453 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4454 newsrv->state |= SRV_NON_STICK;
4455 cur_arg ++;
4456 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004457 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4458 newsrv->state |= SRV_SEND_PROXY;
4459 cur_arg ++;
4460 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004461 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4462 newsrv->check.send_proxy = 1;
4463 cur_arg ++;
4464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 else if (!strcmp(args[cur_arg], "weight")) {
4466 int w;
4467 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004468 if (w < 0 || w > SRV_UWGHT_MAX) {
4469 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4470 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004474 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 cur_arg += 2;
4476 }
4477 else if (!strcmp(args[cur_arg], "minconn")) {
4478 newsrv->minconn = atol(args[cur_arg + 1]);
4479 cur_arg += 2;
4480 }
4481 else if (!strcmp(args[cur_arg], "maxconn")) {
4482 newsrv->maxconn = atol(args[cur_arg + 1]);
4483 cur_arg += 2;
4484 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004485 else if (!strcmp(args[cur_arg], "maxqueue")) {
4486 newsrv->maxqueue = atol(args[cur_arg + 1]);
4487 cur_arg += 2;
4488 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004489 else if (!strcmp(args[cur_arg], "slowstart")) {
4490 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004491 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004492 if (err) {
4493 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4494 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004497 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004498 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004499 cur_arg += 2;
4500 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004501 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004502
4503 if (!*args[cur_arg + 1]) {
4504 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004508 }
4509
4510 newsrv->trackit = strdup(args[cur_arg + 1]);
4511
4512 cur_arg += 2;
4513 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004514 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 global.maxsock++;
4516 do_check = 1;
4517 cur_arg += 1;
4518 }
Willy Tarreau96839092010-03-29 10:02:24 +02004519 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4520 newsrv->state |= SRV_MAINTAIN;
4521 newsrv->state &= ~SRV_RUNNING;
4522 newsrv->health = 0;
4523 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004524 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004525 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004526 if (!strcmp(args[cur_arg + 1], "none"))
4527 newsrv->observe = HANA_OBS_NONE;
4528 else if (!strcmp(args[cur_arg + 1], "layer4"))
4529 newsrv->observe = HANA_OBS_LAYER4;
4530 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4531 if (curproxy->mode != PR_MODE_HTTP) {
4532 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4533 file, linenum, args[cur_arg + 1]);
4534 err_code |= ERR_ALERT;
4535 }
4536 newsrv->observe = HANA_OBS_LAYER7;
4537 }
4538 else {
4539 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004540 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004541 file, linenum, args[cur_arg], args[cur_arg + 1]);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
4545
4546 cur_arg += 2;
4547 }
4548 else if (!strcmp(args[cur_arg], "on-error")) {
4549 if (!strcmp(args[cur_arg + 1], "fastinter"))
4550 newsrv->onerror = HANA_ONERR_FASTINTER;
4551 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4552 newsrv->onerror = HANA_ONERR_FAILCHK;
4553 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4554 newsrv->onerror = HANA_ONERR_SUDDTH;
4555 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4556 newsrv->onerror = HANA_ONERR_MARKDWN;
4557 else {
4558 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004559 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004560 file, linenum, args[cur_arg], args[cur_arg + 1]);
4561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
4563 }
4564
4565 cur_arg += 2;
4566 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004567 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4568 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4569 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4570 else {
4571 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4572 file, linenum, args[cur_arg], args[cur_arg + 1]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576
4577 cur_arg += 2;
4578 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004579 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4580 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4581 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4582 else {
4583 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4584 file, linenum, args[cur_arg], args[cur_arg + 1]);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588
4589 cur_arg += 2;
4590 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004591 else if (!strcmp(args[cur_arg], "error-limit")) {
4592 if (!*args[cur_arg + 1]) {
4593 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4594 file, linenum, args[cur_arg]);
4595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
4597 }
4598
4599 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4600
4601 if (newsrv->consecutive_errors_limit <= 0) {
4602 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4603 file, linenum, args[cur_arg]);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004607 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004608 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004609 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004610 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004611 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004612 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004613
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004615 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4616 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004620
Willy Tarreauef9a3602012-12-08 22:29:20 +01004621 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004622 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004623 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004624 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004625 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004626 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004627 goto out;
4628 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004629
4630 proto = protocol_by_family(sk->ss_family);
4631 if (!proto || !proto->connect) {
4632 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4633 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
4636 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004637
Willy Tarreauef9a3602012-12-08 22:29:20 +01004638 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004639
4640 if (port_low != port_high) {
4641 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004642
4643 if (!port_low || !port_high) {
4644 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4645 file, linenum, args[cur_arg], args[cur_arg + 1]);
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
4649
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004650 if (port_low <= 0 || port_low > 65535 ||
4651 port_high <= 0 || port_high > 65535 ||
4652 port_low > port_high) {
4653 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4654 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004657 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004658 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4659 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4660 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004661 }
4662
Willy Tarreaubaaee002006-06-26 02:48:02 +02004663 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004664 while (*(args[cur_arg])) {
4665 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004666#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4667#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004668 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004669 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4670 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004673 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004674#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004675 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004676 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004677 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004680 }
4681 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004682 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4683 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004684 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004685 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4686 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004687 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4688 char *name, *end;
4689
4690 name = args[cur_arg+1] + 7;
4691 while (isspace(*name))
4692 name++;
4693
4694 end = name;
4695 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4696 end++;
4697
Willy Tarreauef9a3602012-12-08 22:29:20 +01004698 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4699 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4700 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4701 newsrv->conn_src.bind_hdr_len = end - name;
4702 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4703 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4704 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004705
4706 /* now look for an occurrence number */
4707 while (isspace(*end))
4708 end++;
4709 if (*end == ',') {
4710 end++;
4711 name = end;
4712 if (*end == '-')
4713 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004714 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004715 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004716 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004717 }
4718
Willy Tarreauef9a3602012-12-08 22:29:20 +01004719 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004720 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4721 " occurrences values smaller than %d.\n",
4722 file, linenum, MAX_HDR_HISTORY);
4723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
4725 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004726 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004727 struct sockaddr_storage *sk;
4728 int port1, port2;
4729
Willy Tarreau902636f2013-03-10 19:44:48 +01004730 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004731 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004732 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004733 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004734 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004735 goto out;
4736 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004737
4738 proto = protocol_by_family(sk->ss_family);
4739 if (!proto || !proto->connect) {
4740 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4741 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
4744 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004745
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004746 if (port1 != port2) {
4747 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4748 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
4751 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004752 newsrv->conn_src.tproxy_addr = *sk;
4753 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004754 }
4755 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004756#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004757 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004758#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004759 cur_arg += 2;
4760 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004761#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004762 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004763 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004766#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004767 } /* "usesrc" */
4768
4769 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4770#ifdef SO_BINDTODEVICE
4771 if (!*args[cur_arg + 1]) {
4772 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4773 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004776 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004777 free(newsrv->conn_src.iface_name);
4778 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4779 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004780 global.last_checks |= LSTCHK_NETADM;
4781#else
4782 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4783 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004786#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004787 cur_arg += 2;
4788 continue;
4789 }
4790 /* this keyword in not an option of "source" */
4791 break;
4792 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004794 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004795 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4796 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004801 static int srv_dumped;
4802 struct srv_kw *kw;
4803 char *err;
4804
4805 kw = srv_find_kw(args[cur_arg]);
4806 if (kw) {
4807 char *err = NULL;
4808 int code;
4809
4810 if (!kw->parse) {
4811 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4812 file, linenum, args[0], args[1], args[cur_arg]);
4813 cur_arg += 1 + kw->skip ;
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
4817
4818 if (defsrv && !kw->default_ok) {
4819 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4820 file, linenum, args[0], args[1], args[cur_arg]);
4821 cur_arg += 1 + kw->skip ;
4822 err_code |= ERR_ALERT;
4823 continue;
4824 }
4825
4826 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4827 err_code |= code;
4828
4829 if (code) {
4830 if (err && *err) {
4831 indent_msg(&err, 2);
4832 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4833 }
4834 else
4835 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4836 file, linenum, args[0], args[1], args[cur_arg]);
4837 if (code & ERR_FATAL) {
4838 free(err);
4839 cur_arg += 1 + kw->skip;
4840 goto out;
4841 }
4842 }
4843 free(err);
4844 cur_arg += 1 + kw->skip;
4845 continue;
4846 }
4847
4848 err = NULL;
4849 if (!srv_dumped) {
4850 srv_dump_kws(&err);
4851 indent_msg(&err, 4);
4852 srv_dumped = 1;
4853 }
4854
4855 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4856 file, linenum, args[0], args[1], args[cur_arg],
4857 err ? " Registered keywords :" : "", err ? err : "");
4858 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004859
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
4863 }
4864
4865 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09004866 int ret;
4867
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004868 if (newsrv->trackit) {
4869 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4870 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004871 err_code |= ERR_ALERT | ERR_FATAL;
4872 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004873 }
4874
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004875 /* If neither a port nor an addr was specified and no check transport
4876 * layer is forced, then the transport layer used by the checks is the
4877 * same as for the production traffic. Otherwise we use raw_sock by
4878 * default, unless one is specified.
4879 */
Simon Horman66183002013-02-23 10:16:43 +09004880 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004881#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004882 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004883#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004884 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4885 }
Simon Horman66183002013-02-23 10:16:43 +09004886 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004887 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09004888 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004889
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004890 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004891 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004892
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004893 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004894 /* not yet valid, because no port was set on
4895 * the server either. We'll check if we have
4896 * a known port on the first listener.
4897 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004898 struct listener *l;
4899
4900 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004901 newsrv->check.port = get_host_port(&l->addr);
4902 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004903 break;
4904 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004905 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004906 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4908 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004912
Simon Horman69d29f92013-02-23 15:14:19 +09004913 ret = init_check(&newsrv->check,
4914 curproxy->options2 & PR_O2_CHK_ANY,
4915 file, linenum);
4916 if (ret) {
4917 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004918 goto out;
4919 }
4920
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 newsrv->state |= SRV_CHECKED;
4922 }
4923
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004924 if (!defsrv) {
4925 if (newsrv->state & SRV_BACKUP)
4926 curproxy->srv_bck++;
4927 else
4928 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004929
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004930 newsrv->prev_state = newsrv->state;
4931 }
William Lallemanda73203e2012-03-12 12:48:57 +01004932 }
4933
4934 else if (strcmp(args[0], "unique-id-format") == 0) {
4935 if (!*(args[1])) {
4936 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
William Lallemand3203ff42012-11-11 17:30:56 +01004940 if (*(args[2])) {
4941 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
4944 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004945 free(curproxy->conf.uniqueid_format_string);
4946 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004947
Willy Tarreau62a61232013-04-12 18:13:46 +02004948 free(curproxy->conf.uif_file);
4949 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4950 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004951 }
William Lallemanda73203e2012-03-12 12:48:57 +01004952
4953 else if (strcmp(args[0], "unique-id-header") == 0) {
4954 if (!*(args[1])) {
4955 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
4959 free(curproxy->header_unique_id);
4960 curproxy->header_unique_id = strdup(args[1]);
4961 }
4962
William Lallemand723b73a2012-02-08 16:37:49 +01004963 else if (strcmp(args[0], "log-format") == 0) {
4964 if (!*(args[1])) {
4965 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
William Lallemand3203ff42012-11-11 17:30:56 +01004969 if (*(args[2])) {
4970 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
4973 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004974
Willy Tarreau62a61232013-04-12 18:13:46 +02004975 if (curproxy->conf.logformat_string != default_http_log_format &&
4976 curproxy->conf.logformat_string != default_tcp_log_format &&
4977 curproxy->conf.logformat_string != clf_http_log_format)
4978 free(curproxy->conf.logformat_string);
4979 curproxy->conf.logformat_string = strdup(args[1]);
4980
4981 free(curproxy->conf.lfs_file);
4982 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4983 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004984
4985 /* get a chance to improve log-format error reporting by
4986 * reporting the correct line-number when possible.
4987 */
4988 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4989 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4990 file, linenum, curproxy->id);
4991 err_code |= ERR_WARN;
4992 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
William Lallemand723b73a2012-02-08 16:37:49 +01004994
William Lallemand0f99e342011-10-12 17:50:54 +02004995 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4996 /* delete previous herited or defined syslog servers */
4997 struct logsrv *back;
4998
4999 if (*(args[1]) != 0) {
5000 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003 }
5004
William Lallemand723b73a2012-02-08 16:37:49 +01005005 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5006 LIST_DEL(&tmplogsrv->list);
5007 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005008 }
5009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005011 struct logsrv *logsrv;
5012
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005014 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005015 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005016 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005017 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005018 LIST_INIT(&node->list);
5019 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 }
5022 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005023 struct sockaddr_storage *sk;
5024 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005025
5026 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027
William Lallemand0f99e342011-10-12 17:50:54 +02005028 logsrv->facility = get_log_facility(args[2]);
5029 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
5033
Willy Tarreaubaaee002006-06-26 02:48:02 +02005034 }
5035
William Lallemand0f99e342011-10-12 17:50:54 +02005036 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005038 logsrv->level = get_log_level(args[3]);
5039 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
5043
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 }
5045 }
5046
William Lallemand0f99e342011-10-12 17:50:54 +02005047 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005048 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005049 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005050 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005051 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
5054
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005055 }
5056 }
5057
Willy Tarreau902636f2013-03-10 19:44:48 +01005058 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005059 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005060 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005061 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005062 goto out;
5063 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005064
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005065 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005066
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005067 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005068 if (port1 != port2) {
5069 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5070 file, linenum, args[0], args[1]);
5071 err_code |= ERR_ALERT | ERR_FATAL;
5072 goto out;
5073 }
5074
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005075 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005076 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 }
William Lallemand0f99e342011-10-12 17:50:54 +02005078
5079 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
5081 else {
5082 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5083 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 }
5087 }
5088 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005089 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005090 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005091 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005092 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005093
Willy Tarreau977b8e42006-12-29 14:19:17 +01005094 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005096
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005098 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5099 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005103
5104 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005105 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5106 free(curproxy->conn_src.iface_name);
5107 curproxy->conn_src.iface_name = NULL;
5108 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005109
Willy Tarreau902636f2013-03-10 19:44:48 +01005110 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005111 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005112 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005113 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005114 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005115 goto out;
5116 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005117
5118 proto = protocol_by_family(sk->ss_family);
5119 if (!proto || !proto->connect) {
5120 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005121 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
5124 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005125
5126 if (port1 != port2) {
5127 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5128 file, linenum, args[0], args[1]);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
5132
Willy Tarreauef9a3602012-12-08 22:29:20 +01005133 curproxy->conn_src.source_addr = *sk;
5134 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005135
5136 cur_arg = 2;
5137 while (*(args[cur_arg])) {
5138 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005139#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5140#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005141 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005142 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5143 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005146 }
5147#endif
5148 if (!*args[cur_arg + 1]) {
5149 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5150 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005153 }
5154
5155 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005156 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5157 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005158 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005159 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5160 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005161 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5162 char *name, *end;
5163
5164 name = args[cur_arg+1] + 7;
5165 while (isspace(*name))
5166 name++;
5167
5168 end = name;
5169 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5170 end++;
5171
Willy Tarreauef9a3602012-12-08 22:29:20 +01005172 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5173 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5174 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5175 curproxy->conn_src.bind_hdr_len = end - name;
5176 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5177 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5178 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005179
5180 /* now look for an occurrence number */
5181 while (isspace(*end))
5182 end++;
5183 if (*end == ',') {
5184 end++;
5185 name = end;
5186 if (*end == '-')
5187 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005188 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005189 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005190 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005191 }
5192
Willy Tarreauef9a3602012-12-08 22:29:20 +01005193 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005194 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5195 " occurrences values smaller than %d.\n",
5196 file, linenum, MAX_HDR_HISTORY);
5197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
5199 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005200 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005201 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005202
Willy Tarreau902636f2013-03-10 19:44:48 +01005203 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005204 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005205 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005206 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005207 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005208 goto out;
5209 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005210
5211 proto = protocol_by_family(sk->ss_family);
5212 if (!proto || !proto->connect) {
5213 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5214 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
5217 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005218
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005219 if (port1 != port2) {
5220 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5221 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005225 curproxy->conn_src.tproxy_addr = *sk;
5226 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005227 }
5228 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005229#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005230 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005231#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005232#else /* no TPROXY support */
5233 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005234 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005237#endif
5238 cur_arg += 2;
5239 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005240 }
5241
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005242 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5243#ifdef SO_BINDTODEVICE
5244 if (!*args[cur_arg + 1]) {
5245 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005249 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005250 free(curproxy->conn_src.iface_name);
5251 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5252 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005253 global.last_checks |= LSTCHK_NETADM;
5254#else
5255 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5256 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005259#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005260 cur_arg += 2;
5261 continue;
5262 }
5263 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005264 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005269 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5270 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5271 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005276 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005282
5283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005284 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005285 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
5289 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005291 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 }
5296 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005298 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 }
5303 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005305 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 }
5310 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005312 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005313 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005317 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005319 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005320 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005322 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005323 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005324 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005326 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005327 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005329 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005330 }
5331 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005333 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005334 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005336 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005338 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005345
5346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005347 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005348 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005354 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
5359 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005361 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 }
5366 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005368 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
5373 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005375 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005376 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005380 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005382 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005383 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005384 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005385 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005388 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005389
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 if (curproxy == &defproxy) {
5391 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005395 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 if (*(args[1]) == 0) {
5399 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005403
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005404 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005405 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5406 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5407 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005411 err_code |= warnif_cond_conflicts(cond,
5412 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5413 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005414 }
5415 else if (*args[2]) {
5416 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5417 file, linenum, args[0], args[2]);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005422 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005423 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005424 wl->s = strdup(args[1]);
5425 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005426 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 }
5428 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005429 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5431 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005434 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005435
Willy Tarreauade5ec42010-01-28 19:33:49 +01005436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005437 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005438 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 }
5442 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005443 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005444 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005445 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005446 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005448 }
5449 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005450 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005451 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005452 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005453 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 }
5456 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005457 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5459 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 }
5463
Willy Tarreauade5ec42010-01-28 19:33:49 +01005464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005465 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005466 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 }
5470 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005472 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005473 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 }
5477 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005478 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005479 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005480 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005481 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 }
5484 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005485 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005486
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 if (curproxy == &defproxy) {
5488 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005492 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005493 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 if (*(args[1]) == 0) {
5496 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005497 err_code |= ERR_ALERT | ERR_FATAL;
5498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 }
5500
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005501 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005502 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5503 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5504 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
5507 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005508 err_code |= warnif_cond_conflicts(cond,
5509 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5510 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005511 }
5512 else if (*args[2]) {
5513 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5514 file, linenum, args[0], args[2]);
5515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
5517 }
5518
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005519 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005520 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005521 wl->s = strdup(args[1]);
5522 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
5524 else if (!strcmp(args[0], "errorloc") ||
5525 !strcmp(args[0], "errorloc302") ||
5526 !strcmp(args[0], "errorloc303")) { /* error location */
5527 int errnum, errlen;
5528 char *err;
5529
Willy Tarreau977b8e42006-12-29 14:19:17 +01005530 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005531 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005532
Willy Tarreaubaaee002006-06-26 02:48:02 +02005533 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005534 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 }
5538
5539 errnum = atol(args[1]);
5540 if (!strcmp(args[0], "errorloc303")) {
5541 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5542 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5543 } else {
5544 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5545 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5546 }
5547
Willy Tarreau0f772532006-12-23 20:51:41 +01005548 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5549 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005550 chunk_destroy(&curproxy->errmsg[rc]);
5551 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005552 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005555
5556 if (rc >= HTTP_ERR_SIZE) {
5557 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5558 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 free(err);
5560 }
5561 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005562 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5563 int errnum, errlen, fd;
5564 char *err;
5565 struct stat stat;
5566
5567 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005569
5570 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005571 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005574 }
5575
5576 fd = open(args[2], O_RDONLY);
5577 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5578 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5579 file, linenum, args[2], args[1]);
5580 if (fd >= 0)
5581 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005584 }
5585
Willy Tarreau27a674e2009-08-17 07:23:33 +02005586 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005587 errlen = stat.st_size;
5588 } else {
5589 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005590 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005591 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005592 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005593 }
5594
5595 err = malloc(errlen); /* malloc() must succeed during parsing */
5596 errnum = read(fd, err, errlen);
5597 if (errnum != errlen) {
5598 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5599 file, linenum, args[2], args[1]);
5600 close(fd);
5601 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005604 }
5605 close(fd);
5606
5607 errnum = atol(args[1]);
5608 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5609 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005610 chunk_destroy(&curproxy->errmsg[rc]);
5611 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005612 break;
5613 }
5614 }
5615
5616 if (rc >= HTTP_ERR_SIZE) {
5617 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5618 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005619 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005620 free(err);
5621 }
5622 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005623 else if (!strcmp(args[0], "compression")) {
5624 struct comp *comp;
5625 if (curproxy->comp == NULL) {
5626 comp = calloc(1, sizeof(struct comp));
5627 curproxy->comp = comp;
5628 } else {
5629 comp = curproxy->comp;
5630 }
5631
5632 if (!strcmp(args[1], "algo")) {
5633 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005634 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005635
William Lallemand82fe75c2012-10-23 10:25:10 +02005636 cur_arg = 2;
5637 if (!*args[cur_arg]) {
5638 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5639 file, linenum, args[0]);
5640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
5642 }
5643 while (*(args[cur_arg])) {
5644 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5645 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5646 file, linenum, args[0], args[cur_arg]);
5647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
William Lallemand552df672012-11-07 13:21:47 +01005650 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5651 curproxy->comp->algos->end(&ctx);
5652 } else {
5653 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5654 file, linenum, args[0], args[cur_arg]);
5655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
5657 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005658 cur_arg ++;
5659 continue;
5660 }
5661 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005662 else if (!strcmp(args[1], "offload")) {
5663 comp->offload = 1;
5664 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005665 else if (!strcmp(args[1], "type")) {
5666 int cur_arg;
5667 cur_arg = 2;
5668 if (!*args[cur_arg]) {
5669 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5670 file, linenum, args[0]);
5671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
5673 }
5674 while (*(args[cur_arg])) {
5675 comp_append_type(comp, args[cur_arg]);
5676 cur_arg ++;
5677 continue;
5678 }
5679 }
5680 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005681 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005682 file, linenum, args[0]);
5683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
5685 }
5686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005688 struct cfg_kw_list *kwl;
5689 int index;
5690
5691 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5692 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5693 if (kwl->kw[index].section != CFG_LISTEN)
5694 continue;
5695 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5696 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005697 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005698 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005699 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005702 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005703 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005704 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005705 err_code |= ERR_WARN;
5706 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005707 }
Willy Tarreau93893792009-07-23 13:19:11 +02005708 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005709 }
5710 }
5711 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005712
Willy Tarreau6daf3432008-01-22 16:44:08 +01005713 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005714 err_code |= ERR_ALERT | ERR_FATAL;
5715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 }
Willy Tarreau93893792009-07-23 13:19:11 +02005717 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005718 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005719 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720}
5721
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005722int
5723cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5724{
5725
5726 int err_code = 0;
5727 const char *err;
5728
5729 if (!strcmp(args[0], "userlist")) { /* new userlist */
5730 struct userlist *newul;
5731
5732 if (!*args[1]) {
5733 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5734 file, linenum, args[0]);
5735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
5737 }
5738
5739 err = invalid_char(args[1]);
5740 if (err) {
5741 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5742 file, linenum, *err, args[0], args[1]);
5743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
5745 }
5746
5747 for (newul = userlist; newul; newul = newul->next)
5748 if (!strcmp(newul->name, args[1])) {
5749 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5750 file, linenum, args[1]);
5751 err_code |= ERR_WARN;
5752 goto out;
5753 }
5754
5755 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5756 if (!newul) {
5757 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5758 err_code |= ERR_ALERT | ERR_ABORT;
5759 goto out;
5760 }
5761
5762 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5763 newul->name = strdup(args[1]);
5764
5765 if (!newul->groupusers | !newul->name) {
5766 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5767 err_code |= ERR_ALERT | ERR_ABORT;
5768 goto out;
5769 }
5770
5771 newul->next = userlist;
5772 userlist = newul;
5773
5774 } else if (!strcmp(args[0], "group")) { /* new group */
5775 int cur_arg, i;
5776 const char *err;
5777
5778 if (!*args[1]) {
5779 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5780 file, linenum, args[0]);
5781 err_code |= ERR_ALERT | ERR_FATAL;
5782 goto out;
5783 }
5784
5785 err = invalid_char(args[1]);
5786 if (err) {
5787 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5788 file, linenum, *err, args[0], args[1]);
5789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
5791 }
5792
5793 for(i = 0; i < userlist->grpcnt; i++)
5794 if (!strcmp(userlist->groups[i], args[1])) {
5795 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5796 file, linenum, args[1], userlist->name);
5797 err_code |= ERR_ALERT;
5798 goto out;
5799 }
5800
5801 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5802 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5803 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
5806 }
5807
5808 cur_arg = 2;
5809
5810 while (*args[cur_arg]) {
5811 if (!strcmp(args[cur_arg], "users")) {
5812 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5813 cur_arg += 2;
5814 continue;
5815 } else {
5816 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5817 file, linenum, args[0]);
5818 err_code |= ERR_ALERT | ERR_FATAL;
5819 goto out;
5820 }
5821 }
5822
5823 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5824 } else if (!strcmp(args[0], "user")) { /* new user */
5825 struct auth_users *newuser;
5826 int cur_arg;
5827
5828 if (!*args[1]) {
5829 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5830 file, linenum, args[0]);
5831 err_code |= ERR_ALERT | ERR_FATAL;
5832 goto out;
5833 }
5834
5835 for (newuser = userlist->users; newuser; newuser = newuser->next)
5836 if (!strcmp(newuser->user, args[1])) {
5837 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5838 file, linenum, args[1], userlist->name);
5839 err_code |= ERR_ALERT;
5840 goto out;
5841 }
5842
5843 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5844 if (!newuser) {
5845 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5846 err_code |= ERR_ALERT | ERR_ABORT;
5847 goto out;
5848 }
5849
5850 newuser->user = strdup(args[1]);
5851
5852 newuser->next = userlist->users;
5853 userlist->users = newuser;
5854
5855 cur_arg = 2;
5856
5857 while (*args[cur_arg]) {
5858 if (!strcmp(args[cur_arg], "password")) {
5859#ifndef CONFIG_HAP_CRYPT
5860 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5861 file, linenum);
5862 err_code |= ERR_ALERT;
5863#endif
5864 newuser->pass = strdup(args[cur_arg + 1]);
5865 cur_arg += 2;
5866 continue;
5867 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5868 newuser->pass = strdup(args[cur_arg + 1]);
5869 newuser->flags |= AU_O_INSECURE;
5870 cur_arg += 2;
5871 continue;
5872 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005873 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005874 cur_arg += 2;
5875 continue;
5876 } else {
5877 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5878 file, linenum, args[0]);
5879 err_code |= ERR_ALERT | ERR_FATAL;
5880 goto out;
5881 }
5882 }
5883 } else {
5884 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5885 err_code |= ERR_ALERT | ERR_FATAL;
5886 }
5887
5888out:
5889 return err_code;
5890}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891
5892/*
5893 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005894 * Returns the error code, 0 if OK, or any combination of :
5895 * - ERR_ABORT: must abort ASAP
5896 * - ERR_FATAL: we can continue parsing but not start the service
5897 * - ERR_WARN: a warning has been emitted
5898 * - ERR_ALERT: an alert has been emitted
5899 * Only the two first ones can stop processing, the two others are just
5900 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005902int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005904 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 FILE *f;
5906 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005908 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005909
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 if ((f=fopen(file,"r")) == NULL)
5911 return -1;
5912
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005913 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005914 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005915 char *end;
5916 char *args[MAX_LINE_ARGS + 1];
5917 char *line = thisline;
5918
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 linenum++;
5920
5921 end = line + strlen(line);
5922
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005923 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5924 /* Check if we reached the limit and the last char is not \n.
5925 * Watch out for the last line without the terminating '\n'!
5926 */
5927 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005928 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005929 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005930 }
5931
Willy Tarreaubaaee002006-06-26 02:48:02 +02005932 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005933 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005934 line++;
5935
5936 arg = 0;
5937 args[arg] = line;
5938
5939 while (*line && arg < MAX_LINE_ARGS) {
5940 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5941 * C equivalent value. Other combinations left unchanged (eg: \1).
5942 */
5943 if (*line == '\\') {
5944 int skip = 0;
5945 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5946 *line = line[1];
5947 skip = 1;
5948 }
5949 else if (line[1] == 'r') {
5950 *line = '\r';
5951 skip = 1;
5952 }
5953 else if (line[1] == 'n') {
5954 *line = '\n';
5955 skip = 1;
5956 }
5957 else if (line[1] == 't') {
5958 *line = '\t';
5959 skip = 1;
5960 }
5961 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005962 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 unsigned char hex1, hex2;
5964 hex1 = toupper(line[2]) - '0';
5965 hex2 = toupper(line[3]) - '0';
5966 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5967 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5968 *line = (hex1<<4) + hex2;
5969 skip = 3;
5970 }
5971 else {
5972 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005973 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 }
5975 }
5976 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005977 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 end -= skip;
5979 }
5980 line++;
5981 }
5982 else if (*line == '#' || *line == '\n' || *line == '\r') {
5983 /* end of string, end of loop */
5984 *line = 0;
5985 break;
5986 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005987 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005989 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005990 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 line++;
5992 args[++arg] = line;
5993 }
5994 else {
5995 line++;
5996 }
5997 }
5998
5999 /* empty line */
6000 if (!**args)
6001 continue;
6002
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006003 if (*line) {
6004 /* we had to stop due to too many args.
6005 * Let's terminate the string, print the offending part then cut the
6006 * last arg.
6007 */
6008 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6009 line++;
6010 *line = '\0';
6011
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006012 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006013 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006014 err_code |= ERR_ALERT | ERR_FATAL;
6015 args[arg] = line;
6016 }
6017
Willy Tarreau540abe42007-05-02 20:50:16 +02006018 /* zero out remaining args and ensure that at least one entry
6019 * is zeroed out.
6020 */
6021 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006022 args[arg] = line;
6023 }
6024
Willy Tarreau3842f002009-06-14 11:39:52 +02006025 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006026 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006027 char *tmp;
6028
Willy Tarreau3842f002009-06-14 11:39:52 +02006029 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006030 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006031 for (arg=0; *args[arg+1]; arg++)
6032 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006033 *tmp = '\0'; // fix the next arg to \0
6034 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006035 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006036 else if (!strcmp(args[0], "default")) {
6037 kwm = KWM_DEF;
6038 for (arg=0; *args[arg+1]; arg++)
6039 args[arg] = args[arg+1]; // shift args after inversion
6040 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006041
William Lallemand0f99e342011-10-12 17:50:54 +02006042 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6043 strcmp(args[0], "log") != 0) {
6044 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006045 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006046 }
6047
Willy Tarreau977b8e42006-12-29 14:19:17 +01006048 if (!strcmp(args[0], "listen") ||
6049 !strcmp(args[0], "frontend") ||
6050 !strcmp(args[0], "backend") ||
6051 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006052 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006054 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006055 cursection = strdup(args[0]);
6056 }
6057 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006059 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006060 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006061 }
6062 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006063 confsect = CFG_USERLIST;
6064 free(cursection);
6065 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006066 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006067 else if (!strcmp(args[0], "peers")) {
6068 confsect = CFG_PEERS;
6069 free(cursection);
6070 cursection = strdup(args[0]);
6071 }
6072
Willy Tarreaubaaee002006-06-26 02:48:02 +02006073 /* else it's a section keyword */
6074
6075 switch (confsect) {
6076 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006077 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078 break;
6079 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006080 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006082 case CFG_USERLIST:
6083 err_code |= cfg_parse_users(file, linenum, args, kwm);
6084 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006085 case CFG_PEERS:
6086 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6087 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006088 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006089 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006090 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006092
6093 if (err_code & ERR_ABORT)
6094 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006095 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006096 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006097 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006099 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006100}
6101
Willy Tarreaubb925012009-07-23 13:36:36 +02006102/*
6103 * Returns the error code, 0 if OK, or any combination of :
6104 * - ERR_ABORT: must abort ASAP
6105 * - ERR_FATAL: we can continue parsing but not start the service
6106 * - ERR_WARN: a warning has been emitted
6107 * - ERR_ALERT: an alert has been emitted
6108 * Only the two first ones can stop processing, the two others are just
6109 * indicators.
6110 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006111int check_config_validity()
6112{
6113 int cfgerr = 0;
6114 struct proxy *curproxy = NULL;
6115 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006116 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006117 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006118 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006119 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006121 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006122 /*
6123 * Now, check for the integrity of all that we have collected.
6124 */
6125
6126 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006127 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128
Willy Tarreau193b8c62012-11-22 00:17:38 +01006129 if (!global.tune.max_http_hdr)
6130 global.tune.max_http_hdr = MAX_HTTP_HDR;
6131
6132 if (!global.tune.cookie_len)
6133 global.tune.cookie_len = CAPTURE_LEN;
6134
6135 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6136
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006137 /* first, we will invert the proxy list order */
6138 curproxy = NULL;
6139 while (proxy) {
6140 struct proxy *next;
6141
6142 next = proxy->next;
6143 proxy->next = curproxy;
6144 curproxy = proxy;
6145 if (!next)
6146 break;
6147 proxy = next;
6148 }
6149
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006151 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006152 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006153 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006154 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006155 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006156 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006157 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006158
Willy Tarreau050536d2012-10-04 08:47:34 +02006159 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006160 /* proxy ID not set, use automatic numbering with first
6161 * spare entry starting with next_pxid.
6162 */
6163 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6164 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6165 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006166 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006167 next_pxid++;
6168
Willy Tarreau55ea7572007-06-17 19:56:27 +02006169
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006171 /* ensure we don't keep listeners uselessly bound */
6172 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006173 curproxy = curproxy->next;
6174 continue;
6175 }
6176
Willy Tarreau16a21472012-11-19 12:39:59 +01006177 /* number of processes this proxy is bound to */
6178 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6179
Willy Tarreauff01a212009-03-15 13:46:16 +01006180 switch (curproxy->mode) {
6181 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006182 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006183 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006184 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6185 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006186 cfgerr++;
6187 }
6188
6189 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006190 Warning("config : servers will be ignored for %s '%s'.\n",
6191 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006192 break;
6193
6194 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006195 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006196 break;
6197
6198 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006199 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006200 break;
6201 }
6202
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006203 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006204 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006205 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006206 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6207 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006208 cfgerr++;
6209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006210#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006211 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006212 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6213 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006214 cfgerr++;
6215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006217 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006218 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6219 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006220 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006221 }
6222 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006223 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006224 /* If no LB algo is set in a backend, and we're not in
6225 * transparent mode, dispatch mode nor proxy mode, we
6226 * want to use balance roundrobin by default.
6227 */
6228 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6229 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 }
6231 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006232
Willy Tarreau1620ec32011-08-06 17:05:02 +02006233 if (curproxy->options & PR_O_DISPATCH)
6234 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6235 else if (curproxy->options & PR_O_HTTP_PROXY)
6236 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6237 else if (curproxy->options & PR_O_TRANSP)
6238 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006239
Willy Tarreau1620ec32011-08-06 17:05:02 +02006240 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6241 if (curproxy->options & PR_O_DISABLE404) {
6242 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6243 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6244 err_code |= ERR_WARN;
6245 curproxy->options &= ~PR_O_DISABLE404;
6246 }
6247 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6248 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6249 "send-state", proxy_type_str(curproxy), curproxy->id);
6250 err_code |= ERR_WARN;
6251 curproxy->options &= ~PR_O2_CHK_SNDST;
6252 }
Willy Tarreauef781042010-01-27 11:53:01 +01006253 }
6254
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006255 /* if a default backend was specified, let's find it */
6256 if (curproxy->defbe.name) {
6257 struct proxy *target;
6258
Alex Williams96532db2009-11-01 21:27:13 -05006259 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006260 if (!target) {
6261 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6262 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006263 cfgerr++;
6264 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006265 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6266 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006267 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006268 } else {
6269 free(curproxy->defbe.name);
6270 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006271 /* we force the backend to be present on at least all of
6272 * the frontend's processes.
6273 */
6274 target->bind_proc = curproxy->bind_proc ?
6275 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006276
6277 /* Emit a warning if this proxy also has some servers */
6278 if (curproxy->srv) {
6279 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6280 curproxy->id);
6281 err_code |= ERR_WARN;
6282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006283 }
6284 }
6285
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006286 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006287 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6288 /* map jump target for ACT_SETBE in req_rep chain */
6289 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006290 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006291 struct proxy *target;
6292
Willy Tarreaua496b602006-12-17 23:15:24 +01006293 if (exp->action != ACT_SETBE)
6294 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006295
Alex Williams96532db2009-11-01 21:27:13 -05006296 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006297 if (!target) {
6298 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6299 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006300 cfgerr++;
6301 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006302 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6303 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006304 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006305 } else {
6306 free((void *)exp->replace);
6307 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006308 /* we force the backend to be present on at least all of
6309 * the frontend's processes.
6310 */
6311 target->bind_proc = curproxy->bind_proc ?
6312 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006313 }
6314 }
6315 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006316
6317 /* find the target proxy for 'use_backend' rules */
6318 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006319 struct proxy *target;
6320
Alex Williams96532db2009-11-01 21:27:13 -05006321 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006322
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006323 if (!target) {
6324 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6325 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006326 cfgerr++;
6327 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006328 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6329 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006330 cfgerr++;
6331 } else {
6332 free((void *)rule->be.name);
6333 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006334 /* we force the backend to be present on at least all of
6335 * the frontend's processes.
6336 */
6337 target->bind_proc = curproxy->bind_proc ?
6338 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006339 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006340 }
6341
6342 /* find the target proxy for 'use_backend' rules */
6343 list_for_each_entry(srule, &curproxy->server_rules, list) {
6344 struct server *target = findserver(curproxy, srule->srv.name);
6345
6346 if (!target) {
6347 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6348 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6349 cfgerr++;
6350 continue;
6351 }
6352 free((void *)srule->srv.name);
6353 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006354 }
6355
Emeric Brunb982a3d2010-01-04 15:45:53 +01006356 /* find the target table for 'stick' rules */
6357 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6358 struct proxy *target;
6359
Emeric Brun1d33b292010-01-04 15:47:17 +01006360 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6361 if (mrule->flags & STK_IS_STORE)
6362 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6363
Emeric Brunb982a3d2010-01-04 15:45:53 +01006364 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006365 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006366 else
6367 target = curproxy;
6368
6369 if (!target) {
6370 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6371 curproxy->id, mrule->table.name);
6372 cfgerr++;
6373 }
6374 else if (target->table.size == 0) {
6375 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6376 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6377 cfgerr++;
6378 }
Willy Tarreau12785782012-04-27 21:37:17 +02006379 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6380 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006381 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6382 cfgerr++;
6383 }
6384 else {
6385 free((void *)mrule->table.name);
6386 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006387 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006388 }
6389 }
6390
6391 /* find the target table for 'store response' rules */
6392 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6393 struct proxy *target;
6394
Emeric Brun1d33b292010-01-04 15:47:17 +01006395 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6396
Emeric Brunb982a3d2010-01-04 15:45:53 +01006397 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006398 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006399 else
6400 target = curproxy;
6401
6402 if (!target) {
6403 Alert("Proxy '%s': unable to find store table '%s'.\n",
6404 curproxy->id, mrule->table.name);
6405 cfgerr++;
6406 }
6407 else if (target->table.size == 0) {
6408 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6409 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6410 cfgerr++;
6411 }
Willy Tarreau12785782012-04-27 21:37:17 +02006412 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6413 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006414 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6415 cfgerr++;
6416 }
6417 else {
6418 free((void *)mrule->table.name);
6419 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006420 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006421 }
6422 }
6423
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006424 /* find the target table for 'tcp-request' layer 4 rules */
6425 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6426 struct proxy *target;
6427
Willy Tarreaub4c84932013-07-23 19:15:30 +02006428 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006429 continue;
6430
6431 if (trule->act_prm.trk_ctr.table.n)
6432 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6433 else
6434 target = curproxy;
6435
6436 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006437 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6438 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006439 1 + tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006440 cfgerr++;
6441 }
6442 else if (target->table.size == 0) {
6443 Alert("Proxy '%s': table '%s' used but not configured.\n",
6444 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6445 cfgerr++;
6446 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006447 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6448 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6449 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006450 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006451 cfgerr++;
6452 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006453 else {
6454 free(trule->act_prm.trk_ctr.table.n);
6455 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006456 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006457 * to pass a list of counters to track and allocate them right here using
6458 * stktable_alloc_data_type().
6459 */
6460 }
6461 }
6462
Willy Tarreaud1f96522010-08-03 19:34:32 +02006463 /* find the target table for 'tcp-request' layer 6 rules */
6464 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6465 struct proxy *target;
6466
Willy Tarreaub4c84932013-07-23 19:15:30 +02006467 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006468 continue;
6469
6470 if (trule->act_prm.trk_ctr.table.n)
6471 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6472 else
6473 target = curproxy;
6474
6475 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006476 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6477 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006478 1 + tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006479 cfgerr++;
6480 }
6481 else if (target->table.size == 0) {
6482 Alert("Proxy '%s': table '%s' used but not configured.\n",
6483 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6484 cfgerr++;
6485 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006486 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6487 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6488 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006489 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006490 cfgerr++;
6491 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006492 else {
6493 free(trule->act_prm.trk_ctr.table.n);
6494 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006495 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006496 * to pass a list of counters to track and allocate them right here using
6497 * stktable_alloc_data_type().
6498 */
6499 }
6500 }
6501
Emeric Brun32da3c42010-09-23 18:39:19 +02006502 if (curproxy->table.peers.name) {
6503 struct peers *curpeers = peers;
6504
6505 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6506 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6507 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006508 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006509 break;
6510 }
6511 }
6512
6513 if (!curpeers) {
6514 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6515 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006516 free((void *)curproxy->table.peers.name);
6517 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006518 cfgerr++;
6519 }
6520 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006521 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6522 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006523 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006524 cfgerr++;
6525 }
6526 }
6527
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006528 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006529 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006530 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6531 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6532 "proxy", curproxy->id);
6533 cfgerr++;
6534 goto out_uri_auth_compat;
6535 }
6536
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006537 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006538 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006539 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006540 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006541
Willy Tarreau95fa4692010-02-01 13:05:50 +01006542 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6543 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006544
6545 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006546 uri_auth_compat_req[i++] = "realm";
6547 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6548 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006549
Willy Tarreau95fa4692010-02-01 13:05:50 +01006550 uri_auth_compat_req[i++] = "unless";
6551 uri_auth_compat_req[i++] = "{";
6552 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6553 uri_auth_compat_req[i++] = "}";
6554 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006555
Willy Tarreauff011f22011-01-06 17:51:27 +01006556 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6557 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006558 cfgerr++;
6559 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006560 }
6561
Willy Tarreauff011f22011-01-06 17:51:27 +01006562 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006563
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006564 if (curproxy->uri_auth->auth_realm) {
6565 free(curproxy->uri_auth->auth_realm);
6566 curproxy->uri_auth->auth_realm = NULL;
6567 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006568
6569 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006570 }
6571out_uri_auth_compat:
6572
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006573 /* compile the log format */
6574 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006575 if (curproxy->conf.logformat_string != default_http_log_format &&
6576 curproxy->conf.logformat_string != default_tcp_log_format &&
6577 curproxy->conf.logformat_string != clf_http_log_format)
6578 free(curproxy->conf.logformat_string);
6579 curproxy->conf.logformat_string = NULL;
6580 free(curproxy->conf.lfs_file);
6581 curproxy->conf.lfs_file = NULL;
6582 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006583 }
6584
Willy Tarreau62a61232013-04-12 18:13:46 +02006585 if (curproxy->conf.logformat_string) {
6586 curproxy->conf.args.ctx = ARGC_LOG;
6587 curproxy->conf.args.file = curproxy->conf.lfs_file;
6588 curproxy->conf.args.line = curproxy->conf.lfs_line;
6589 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006590 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006591 curproxy->conf.args.file = NULL;
6592 curproxy->conf.args.line = 0;
6593 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006594
Willy Tarreau62a61232013-04-12 18:13:46 +02006595 if (curproxy->conf.uniqueid_format_string) {
6596 curproxy->conf.args.ctx = ARGC_UIF;
6597 curproxy->conf.args.file = curproxy->conf.uif_file;
6598 curproxy->conf.args.line = curproxy->conf.uif_line;
6599 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006600 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006601 curproxy->conf.args.file = NULL;
6602 curproxy->conf.args.line = 0;
6603 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006604
6605 /* only now we can check if some args remain unresolved */
6606 cfgerr += smp_resolve_args(curproxy);
6607 if (!cfgerr)
6608 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006609
Willy Tarreau2738a142006-07-08 17:28:09 +02006610 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006611 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006612 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006613 (!curproxy->timeout.connect ||
6614 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006615 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006616 " | While not properly invalid, you will certainly encounter various problems\n"
6617 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006618 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006619 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006620 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006621 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006622
Willy Tarreau1fa31262007-12-03 00:36:16 +01006623 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6624 * We must still support older configurations, so let's find out whether those
6625 * parameters have been set or must be copied from contimeouts.
6626 */
6627 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006628 if (!curproxy->timeout.tarpit ||
6629 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006630 /* tarpit timeout not set. We search in the following order:
6631 * default.tarpit, curr.connect, default.connect.
6632 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006633 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006634 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006635 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006636 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006637 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006638 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006639 }
6640 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006641 (!curproxy->timeout.queue ||
6642 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006643 /* queue timeout not set. We search in the following order:
6644 * default.queue, curr.connect, default.connect.
6645 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006646 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006647 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006648 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006649 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006650 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006651 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006652 }
6653 }
6654
Willy Tarreau1620ec32011-08-06 17:05:02 +02006655 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006656 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6657 curproxy->check_req = (char *)malloc(curproxy->check_len);
6658 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006659 }
6660
Willy Tarreau193b8c62012-11-22 00:17:38 +01006661 /* ensure that cookie capture length is not too large */
6662 if (curproxy->capture_len >= global.tune.cookie_len) {
6663 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6664 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6665 err_code |= ERR_WARN;
6666 curproxy->capture_len = global.tune.cookie_len - 1;
6667 }
6668
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006669 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006670 if (curproxy->nb_req_cap) {
6671 if (curproxy->mode == PR_MODE_HTTP) {
6672 curproxy->req_cap_pool = create_pool("ptrcap",
6673 curproxy->nb_req_cap * sizeof(char *),
6674 MEM_F_SHARED);
6675 } else {
6676 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6677 proxy_type_str(curproxy), curproxy->id);
6678 err_code |= ERR_WARN;
6679 curproxy->to_log &= ~LW_REQHDR;
6680 curproxy->nb_req_cap = 0;
6681 }
6682 }
6683
6684 if (curproxy->nb_rsp_cap) {
6685 if (curproxy->mode == PR_MODE_HTTP) {
6686 curproxy->rsp_cap_pool = create_pool("ptrcap",
6687 curproxy->nb_rsp_cap * sizeof(char *),
6688 MEM_F_SHARED);
6689 } else {
6690 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6691 proxy_type_str(curproxy), curproxy->id);
6692 err_code |= ERR_WARN;
6693 curproxy->to_log &= ~LW_REQHDR;
6694 curproxy->nb_rsp_cap = 0;
6695 }
6696 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006697
Willy Tarreaubaaee002006-06-26 02:48:02 +02006698 /* first, we will invert the servers list order */
6699 newsrv = NULL;
6700 while (curproxy->srv) {
6701 struct server *next;
6702
6703 next = curproxy->srv->next;
6704 curproxy->srv->next = newsrv;
6705 newsrv = curproxy->srv;
6706 if (!next)
6707 break;
6708 curproxy->srv = next;
6709 }
6710
Willy Tarreaudd701652010-05-25 23:03:02 +02006711 /* assign automatic UIDs to servers which don't have one yet */
6712 next_id = 1;
6713 newsrv = curproxy->srv;
6714 while (newsrv != NULL) {
6715 if (!newsrv->puid) {
6716 /* server ID not set, use automatic numbering with first
6717 * spare entry starting with next_svid.
6718 */
6719 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6720 newsrv->conf.id.key = newsrv->puid = next_id;
6721 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6722 }
6723 next_id++;
6724 newsrv = newsrv->next;
6725 }
6726
Willy Tarreau20697042007-11-15 23:26:18 +01006727 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006728 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006729
Willy Tarreau62c3be22012-01-20 13:12:32 +01006730 /*
6731 * If this server supports a maxconn parameter, it needs a dedicated
6732 * tasks to fill the emptied slots when a connection leaves.
6733 * Also, resolve deferred tracking dependency if needed.
6734 */
6735 newsrv = curproxy->srv;
6736 while (newsrv != NULL) {
6737 if (newsrv->minconn > newsrv->maxconn) {
6738 /* Only 'minconn' was specified, or it was higher than or equal
6739 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6740 * this will avoid further useless expensive computations.
6741 */
6742 newsrv->maxconn = newsrv->minconn;
6743 } else if (newsrv->maxconn && !newsrv->minconn) {
6744 /* minconn was not specified, so we set it to maxconn */
6745 newsrv->minconn = newsrv->maxconn;
6746 }
6747
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006748#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006749 if (newsrv->use_ssl || newsrv->check.use_ssl)
6750 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006751#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006752
Willy Tarreau62c3be22012-01-20 13:12:32 +01006753 if (newsrv->trackit) {
6754 struct proxy *px;
6755 struct server *srv;
6756 char *pname, *sname;
6757
6758 pname = newsrv->trackit;
6759 sname = strrchr(pname, '/');
6760
6761 if (sname)
6762 *sname++ = '\0';
6763 else {
6764 sname = pname;
6765 pname = NULL;
6766 }
6767
6768 if (pname) {
6769 px = findproxy(pname, PR_CAP_BE);
6770 if (!px) {
6771 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6772 proxy_type_str(curproxy), curproxy->id,
6773 newsrv->id, pname);
6774 cfgerr++;
6775 goto next_srv;
6776 }
6777 } else
6778 px = curproxy;
6779
6780 srv = findserver(px, sname);
6781 if (!srv) {
6782 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6783 proxy_type_str(curproxy), curproxy->id,
6784 newsrv->id, sname);
6785 cfgerr++;
6786 goto next_srv;
6787 }
6788
6789 if (!(srv->state & SRV_CHECKED)) {
6790 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6791 "tracking as it does not have checks enabled.\n",
6792 proxy_type_str(curproxy), curproxy->id,
6793 newsrv->id, px->id, srv->id);
6794 cfgerr++;
6795 goto next_srv;
6796 }
6797
6798 if (curproxy != px &&
6799 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6800 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6801 "tracking: disable-on-404 option inconsistency.\n",
6802 proxy_type_str(curproxy), curproxy->id,
6803 newsrv->id, px->id, srv->id);
6804 cfgerr++;
6805 goto next_srv;
6806 }
6807
6808 /* if the other server is forced disabled, we have to do the same here */
6809 if (srv->state & SRV_MAINTAIN) {
6810 newsrv->state |= SRV_MAINTAIN;
6811 newsrv->state &= ~SRV_RUNNING;
6812 newsrv->health = 0;
6813 }
6814
6815 newsrv->track = srv;
6816 newsrv->tracknext = srv->tracknext;
6817 srv->tracknext = newsrv;
6818
6819 free(newsrv->trackit);
6820 newsrv->trackit = NULL;
6821 }
6822 next_srv:
6823 newsrv = newsrv->next;
6824 }
6825
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006826 /* We have to initialize the server lookup mechanism depending
6827 * on what LB algorithm was choosen.
6828 */
6829
6830 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6831 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6832 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006833 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6834 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6835 init_server_map(curproxy);
6836 } else {
6837 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6838 fwrr_init_server_groups(curproxy);
6839 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006840 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006841
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006842 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006843 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6844 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6845 fwlc_init_server_tree(curproxy);
6846 } else {
6847 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6848 fas_init_server_tree(curproxy);
6849 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006850 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006851
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006852 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006853 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6854 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6855 chash_init_server_tree(curproxy);
6856 } else {
6857 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6858 init_server_map(curproxy);
6859 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006860 break;
6861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006862
6863 if (curproxy->options & PR_O_LOGASAP)
6864 curproxy->to_log &= ~LW_BYTES;
6865
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006866 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006867 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006868 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6869 proxy_type_str(curproxy), curproxy->id);
6870 err_code |= ERR_WARN;
6871 }
6872
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006873 if (curproxy->mode != PR_MODE_HTTP) {
6874 int optnum;
6875
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006876 if (curproxy->uri_auth) {
6877 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6878 proxy_type_str(curproxy), curproxy->id);
6879 err_code |= ERR_WARN;
6880 curproxy->uri_auth = NULL;
6881 }
6882
Willy Tarreau87cf5142011-08-19 22:57:24 +02006883 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006884 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6885 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6886 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006887 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006888 }
6889
6890 if (curproxy->options & PR_O_ORGTO) {
6891 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6892 "originalto", proxy_type_str(curproxy), curproxy->id);
6893 err_code |= ERR_WARN;
6894 curproxy->options &= ~PR_O_ORGTO;
6895 }
6896
6897 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6898 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6899 (curproxy->cap & cfg_opts[optnum].cap) &&
6900 (curproxy->options & cfg_opts[optnum].val)) {
6901 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6902 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6903 err_code |= ERR_WARN;
6904 curproxy->options &= ~cfg_opts[optnum].val;
6905 }
6906 }
6907
6908 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6909 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6910 (curproxy->cap & cfg_opts2[optnum].cap) &&
6911 (curproxy->options2 & cfg_opts2[optnum].val)) {
6912 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6913 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6914 err_code |= ERR_WARN;
6915 curproxy->options2 &= ~cfg_opts2[optnum].val;
6916 }
6917 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006918
Pieter Baauwd551fb52013-05-08 22:49:23 +02006919#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006920 if (curproxy->conn_src.bind_hdr_occ) {
6921 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006922 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006923 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006924 err_code |= ERR_WARN;
6925 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006926#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006927 }
6928
Willy Tarreaubaaee002006-06-26 02:48:02 +02006929 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006930 * ensure that we're not cross-dressing a TCP server into HTTP.
6931 */
6932 newsrv = curproxy->srv;
6933 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006934 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006935 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6936 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006937 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006938 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006939
Willy Tarreau0cec3312011-10-31 13:49:26 +01006940 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6941 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6942 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6943 err_code |= ERR_WARN;
6944 }
6945
Willy Tarreau82ffa392013-08-13 17:19:08 +02006946 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6947 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6948 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6949 err_code |= ERR_WARN;
6950 }
6951
Pieter Baauwd551fb52013-05-08 22:49:23 +02006952#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006953 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6954 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006955 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 +01006956 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006957 err_code |= ERR_WARN;
6958 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006959#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006960 newsrv = newsrv->next;
6961 }
6962
Willy Tarreauc1a21672009-08-16 22:37:44 +02006963 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006964 if (!curproxy->accept)
6965 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006966
Willy Tarreauc1a21672009-08-16 22:37:44 +02006967 if (curproxy->tcp_req.inspect_delay ||
6968 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006969 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006970
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006971 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006972 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006973 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006974 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006975
6976 /* both TCP and HTTP must check switching rules */
6977 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6978 }
6979
6980 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006981 if (curproxy->tcp_req.inspect_delay ||
6982 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6983 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6984
Emeric Brun97679e72010-09-23 17:56:44 +02006985 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6986 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6987
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006988 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006989 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006990 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006991 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006992
6993 /* If the backend does requires RDP cookie persistence, we have to
6994 * enable the corresponding analyser.
6995 */
6996 if (curproxy->options2 & PR_O2_RDPC_PRST)
6997 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6998 }
6999
Emeric Brunc52962f2012-11-15 18:28:02 +01007000#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007001 /* Configure SSL for each bind line.
7002 * Note: if configuration fails at some point, the ->ctx member
7003 * remains NULL so that listeners can later detach.
7004 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007005 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007006 if (!bind_conf->is_ssl) {
7007 if (bind_conf->default_ctx) {
7008 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7009 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7010 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007011 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007012 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007013 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007014 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007015 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007016 cfgerr++;
7017 continue;
7018 }
7019
Emeric Brun4b3091e2012-09-24 15:48:52 +02007020 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007021 Alert("Unable to allocate SSL session cache.\n");
7022 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007023 continue;
7024 }
7025
Emeric Brunfc0421f2012-09-07 17:30:07 +02007026 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007027 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007028 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007029#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007030
Willy Tarreaue6b98942007-10-29 01:09:36 +01007031 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007032 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007033 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007034 if (!listener->luid) {
7035 /* listener ID not set, use automatic numbering with first
7036 * spare entry starting with next_luid.
7037 */
7038 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7039 listener->conf.id.key = listener->luid = next_id;
7040 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007041 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007042 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007043
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007044 /* enable separate counters */
7045 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7046 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007047 if (!listener->name)
7048 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007049 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007050
Willy Tarreaue6b98942007-10-29 01:09:36 +01007051 if (curproxy->options & PR_O_TCP_NOLING)
7052 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007053 if (!listener->maxconn)
7054 listener->maxconn = curproxy->maxconn;
7055 if (!listener->backlog)
7056 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007057 if (!listener->maxaccept)
7058 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7059
7060 /* we want to have an optimal behaviour on single process mode to
7061 * maximize the work at once, but in multi-process we want to keep
7062 * some fairness between processes, so we target half of the max
7063 * number of events to be balanced over all the processes the proxy
7064 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7065 * used to disable the limit.
7066 */
7067 if (listener->maxaccept > 0) {
7068 if (nbproc > 1)
7069 listener->maxaccept = (listener->maxaccept + 1) / 2;
7070 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7071 }
7072
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007073 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007074 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007075 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007076 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007077
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007078 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7079 listener->options |= LI_O_TCP_RULES;
7080
Willy Tarreaude3041d2010-05-31 10:56:17 +02007081 if (curproxy->mon_mask.s_addr)
7082 listener->options |= LI_O_CHK_MONNET;
7083
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007084 /* smart accept mode is automatic in HTTP mode */
7085 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007086 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007087 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7088 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007089 }
7090
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007091 /* Release unused SSL configs */
7092 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7093 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007094 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007095#ifdef USE_OPENSSL
7096 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007097 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007098 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007099 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007100 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007101#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007102 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007103
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007104 /* Check multi-process mode compatibility for the current proxy */
7105 if (global.nbproc > 1) {
7106 int nbproc = 0;
7107 if (curproxy->bind_proc) {
7108 int proc;
7109 for (proc = 0; proc < global.nbproc; proc++) {
7110 if (curproxy->bind_proc & (1 << proc)) {
7111 nbproc++;
7112 }
7113 }
7114 } else {
7115 nbproc = global.nbproc;
7116 }
7117 if (curproxy->table.peers.name) {
7118 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7119 curproxy->id);
7120 cfgerr++;
7121 }
7122 if (nbproc > 1) {
7123 if (curproxy->uri_auth) {
7124 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7125 curproxy->id);
7126 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7127 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7128 curproxy->id);
7129 }
7130 }
7131 if (curproxy->appsession_name) {
7132 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7133 curproxy->id);
7134 }
7135 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7136 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7137 curproxy->id);
7138 }
7139 }
7140 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007141
7142 /* create the task associated with the proxy */
7143 curproxy->task = task_new();
7144 if (curproxy->task) {
7145 curproxy->task->context = curproxy;
7146 curproxy->task->process = manage_proxy;
7147 /* no need to queue, it will be done automatically if some
7148 * listener gets limited.
7149 */
7150 curproxy->task->expire = TICK_ETERNITY;
7151 } else {
7152 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7153 curproxy->id);
7154 cfgerr++;
7155 }
7156
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157 curproxy = curproxy->next;
7158 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007159
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007160 /* Check multi-process mode compatibility */
7161 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007162 if (global.stats_fe && !global.stats_fe->bind_proc) {
7163 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 +01007164 }
7165 }
7166
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007167 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7168 struct auth_users *curuser;
7169 int g;
7170
7171 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7172 unsigned int group_mask = 0;
7173 char *group = NULL;
7174
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007175 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007176 continue;
7177
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007178 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007179
7180 for (g = 0; g < curuserlist->grpcnt; g++)
7181 if (!strcmp(curuserlist->groups[g], group))
7182 break;
7183
7184 if (g == curuserlist->grpcnt) {
7185 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7186 curuserlist->name, group, curuser->user);
7187 err_code |= ERR_ALERT | ERR_FATAL;
7188 goto out;
7189 }
7190
7191 group_mask |= (1 << g);
7192 }
7193
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007194 free(curuser->u.groups);
7195 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007196 }
7197
7198 for (g = 0; g < curuserlist->grpcnt; g++) {
7199 char *user = NULL;
7200
7201 if (!curuserlist->groupusers[g])
7202 continue;
7203
7204 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7205 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7206 if (!strcmp(curuser->user, user))
7207 break;
7208
7209 if (!curuser) {
7210 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7211 curuserlist->name, user, curuserlist->groups[g]);
7212 err_code |= ERR_ALERT | ERR_FATAL;
7213 goto out;
7214 }
7215
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007216 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007217 }
7218
7219 free(curuserlist->groupusers[g]);
7220 }
7221
7222 free(curuserlist->groupusers);
7223
7224#ifdef DEBUG_AUTH
7225 for (g = 0; g < curuserlist->grpcnt; g++) {
7226 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7227
7228 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007229 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007230 fprintf(stderr, " %s", curuser->user);
7231 }
7232
7233 fprintf(stderr, "\n");
7234 }
7235#endif
7236
Willy Tarreaufbb78422011-06-05 15:38:35 +02007237 }
7238
7239 /* automatically compute fullconn if not set. We must not do it in the
7240 * loop above because cross-references are not yet fully resolved.
7241 */
7242 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7243 /* If <fullconn> is not set, let's set it to 10% of the sum of
7244 * the possible incoming frontend's maxconns.
7245 */
7246 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7247 struct proxy *fe;
7248 int total = 0;
7249
7250 /* sum up the number of maxconns of frontends which
7251 * reference this backend at least once or which are
7252 * the same one ('listen').
7253 */
7254 for (fe = proxy; fe; fe = fe->next) {
7255 struct switching_rule *rule;
7256 struct hdr_exp *exp;
7257 int found = 0;
7258
7259 if (!(fe->cap & PR_CAP_FE))
7260 continue;
7261
7262 if (fe == curproxy) /* we're on a "listen" instance */
7263 found = 1;
7264
7265 if (fe->defbe.be == curproxy) /* "default_backend" */
7266 found = 1;
7267
7268 /* check if a "use_backend" rule matches */
7269 if (!found) {
7270 list_for_each_entry(rule, &fe->switching_rules, list) {
7271 if (rule->be.backend == curproxy) {
7272 found = 1;
7273 break;
7274 }
7275 }
7276 }
7277
7278 /* check if a "reqsetbe" rule matches */
7279 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7280 if (exp->action == ACT_SETBE &&
7281 (struct proxy *)exp->replace == curproxy) {
7282 found = 1;
7283 break;
7284 }
7285 }
7286
7287 /* now we've checked all possible ways to reference a backend
7288 * from a frontend.
7289 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007290 if (!found)
7291 continue;
7292 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007293 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007294 /* we have the sum of the maxconns in <total>. We only
7295 * keep 10% of that sum to set the default fullconn, with
7296 * a hard minimum of 1 (to avoid a divide by zero).
7297 */
7298 curproxy->fullconn = (total + 9) / 10;
7299 if (!curproxy->fullconn)
7300 curproxy->fullconn = 1;
7301 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007302 }
7303
Willy Tarreau056f5682010-06-06 15:51:11 +02007304 /* initialize stick-tables on backend capable proxies. This must not
7305 * be done earlier because the data size may be discovered while parsing
7306 * other proxies.
7307 */
7308 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007309 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007310
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007311 /*
7312 * Recount currently required checks.
7313 */
7314
7315 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7316 int optnum;
7317
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007318 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7319 if (curproxy->options & cfg_opts[optnum].val)
7320 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007321
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007322 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7323 if (curproxy->options2 & cfg_opts2[optnum].val)
7324 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007325 }
7326
Willy Tarreau122541c2011-09-07 21:24:49 +02007327 if (peers) {
7328 struct peers *curpeers = peers, **last;
7329 struct peer *p, *pb;
7330
7331 /* Remove all peers sections which don't have a valid listener.
7332 * This can happen when a peers section is never referenced and
7333 * does not contain a local peer.
7334 */
7335 last = &peers;
7336 while (*last) {
7337 curpeers = *last;
7338 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007339 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007340 last = &curpeers->next;
7341 continue;
7342 }
7343
7344 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7345 curpeers->id, localpeer);
7346
7347 p = curpeers->remote;
7348 while (p) {
7349 pb = p->next;
7350 free(p->id);
7351 free(p);
7352 p = pb;
7353 }
7354
7355 /* Destroy and unlink this curpeers section.
7356 * Note: curpeers is backed up into *last.
7357 */
7358 free(curpeers->id);
7359 curpeers = curpeers->next;
7360 free(*last);
7361 *last = curpeers;
7362 }
7363 }
7364
Willy Tarreau34eb6712011-10-24 18:15:04 +02007365 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007366 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007367 MEM_F_SHARED);
7368
Willy Tarreaubb925012009-07-23 13:36:36 +02007369 if (cfgerr > 0)
7370 err_code |= ERR_ALERT | ERR_FATAL;
7371 out:
7372 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007373}
7374
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007375/*
7376 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7377 * parsing sessions.
7378 */
7379void cfg_register_keywords(struct cfg_kw_list *kwl)
7380{
7381 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7382}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007383
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007384/*
7385 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7386 */
7387void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7388{
7389 LIST_DEL(&kwl->list);
7390 LIST_INIT(&kwl->list);
7391}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007392
7393/*
7394 * Local variables:
7395 * c-indent-level: 8
7396 * c-basic-offset: 8
7397 * End:
7398 */