blob: 0303db8615bb565eed029e631349511ac8270411 [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
Simon Horman69d29f92013-02-23 15:14:19 +09004302 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman125d0992013-02-24 17:23:38 +09004303 newsrv->check.health = newsrv->rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004304 newsrv->check.server = newsrv;
4305
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004306 cur_arg = 3;
4307 } else {
4308 newsrv = &curproxy->defsrv;
4309 cur_arg = 1;
4310 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004311
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004313 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 newsrv->cookie = strdup(args[cur_arg + 1]);
4315 newsrv->cklen = strlen(args[cur_arg + 1]);
4316 cur_arg += 2;
4317 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004318 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004319 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4320 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4321 cur_arg += 2;
4322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004324 if (!*args[cur_arg + 1]) {
4325 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4326 file, linenum, args[cur_arg]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004332 if (newsrv->rise <= 0) {
4333 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4334 file, linenum, args[cur_arg]);
4335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
4337 }
4338
Simon Horman125d0992013-02-24 17:23:38 +09004339 if (newsrv->check.health)
4340 newsrv->check.health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 cur_arg += 2;
4342 }
4343 else if (!strcmp(args[cur_arg], "fall")) {
4344 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004345
4346 if (!*args[cur_arg + 1]) {
4347 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4348 file, linenum, args[cur_arg]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
4353 if (newsrv->fall <= 0) {
4354 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4355 file, linenum, args[cur_arg]);
4356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
4358 }
4359
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 cur_arg += 2;
4361 }
4362 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004363 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4364 if (err) {
4365 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4366 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004369 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004370 if (val <= 0) {
4371 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4372 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004375 }
Simon Horman66183002013-02-23 10:16:43 +09004376 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 cur_arg += 2;
4378 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004379 else if (!strcmp(args[cur_arg], "fastinter")) {
4380 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4381 if (err) {
4382 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4383 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004386 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004387 if (val <= 0) {
4388 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4389 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004392 }
Simon Horman66183002013-02-23 10:16:43 +09004393 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004394 cur_arg += 2;
4395 }
4396 else if (!strcmp(args[cur_arg], "downinter")) {
4397 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4398 if (err) {
4399 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4400 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004403 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004404 if (val <= 0) {
4405 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4406 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004409 }
Simon Horman66183002013-02-23 10:16:43 +09004410 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004411 cur_arg += 2;
4412 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004413 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004414 struct sockaddr_storage *sk;
4415 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004416 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004417
Willy Tarreau902636f2013-03-10 19:44:48 +01004418 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004419 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004420 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004421 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004422 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004423 goto out;
4424 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004425
4426 proto = protocol_by_family(sk->ss_family);
4427 if (!proto || !proto->connect) {
4428 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004429 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004433
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004434 if (port1 != port2) {
4435 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4436 file, linenum, args[cur_arg], args[cur_arg + 1]);
4437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
4439 }
4440
Simon Horman66183002013-02-23 10:16:43 +09004441 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004442 cur_arg += 2;
4443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004445 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 cur_arg += 2;
4447 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004448 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 newsrv->state |= SRV_BACKUP;
4450 cur_arg ++;
4451 }
Simon Hormanfa461682011-06-25 09:39:49 +09004452 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4453 newsrv->state |= SRV_NON_STICK;
4454 cur_arg ++;
4455 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004456 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4457 newsrv->state |= SRV_SEND_PROXY;
4458 cur_arg ++;
4459 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004460 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4461 newsrv->check.send_proxy = 1;
4462 cur_arg ++;
4463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 else if (!strcmp(args[cur_arg], "weight")) {
4465 int w;
4466 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004467 if (w < 0 || w > SRV_UWGHT_MAX) {
4468 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4469 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004473 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 cur_arg += 2;
4475 }
4476 else if (!strcmp(args[cur_arg], "minconn")) {
4477 newsrv->minconn = atol(args[cur_arg + 1]);
4478 cur_arg += 2;
4479 }
4480 else if (!strcmp(args[cur_arg], "maxconn")) {
4481 newsrv->maxconn = atol(args[cur_arg + 1]);
4482 cur_arg += 2;
4483 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004484 else if (!strcmp(args[cur_arg], "maxqueue")) {
4485 newsrv->maxqueue = atol(args[cur_arg + 1]);
4486 cur_arg += 2;
4487 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004488 else if (!strcmp(args[cur_arg], "slowstart")) {
4489 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004490 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004491 if (err) {
4492 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4493 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004496 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004497 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004498 cur_arg += 2;
4499 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004500 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004501
4502 if (!*args[cur_arg + 1]) {
4503 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4504 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004507 }
4508
4509 newsrv->trackit = strdup(args[cur_arg + 1]);
4510
4511 cur_arg += 2;
4512 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004513 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 global.maxsock++;
4515 do_check = 1;
4516 cur_arg += 1;
4517 }
Willy Tarreau96839092010-03-29 10:02:24 +02004518 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4519 newsrv->state |= SRV_MAINTAIN;
4520 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09004521 newsrv->check.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004522 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004523 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004524 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004525 if (!strcmp(args[cur_arg + 1], "none"))
4526 newsrv->observe = HANA_OBS_NONE;
4527 else if (!strcmp(args[cur_arg + 1], "layer4"))
4528 newsrv->observe = HANA_OBS_LAYER4;
4529 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4530 if (curproxy->mode != PR_MODE_HTTP) {
4531 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4532 file, linenum, args[cur_arg + 1]);
4533 err_code |= ERR_ALERT;
4534 }
4535 newsrv->observe = HANA_OBS_LAYER7;
4536 }
4537 else {
4538 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004539 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004540 file, linenum, args[cur_arg], args[cur_arg + 1]);
4541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
4543 }
4544
4545 cur_arg += 2;
4546 }
4547 else if (!strcmp(args[cur_arg], "on-error")) {
4548 if (!strcmp(args[cur_arg + 1], "fastinter"))
4549 newsrv->onerror = HANA_ONERR_FASTINTER;
4550 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4551 newsrv->onerror = HANA_ONERR_FAILCHK;
4552 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4553 newsrv->onerror = HANA_ONERR_SUDDTH;
4554 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4555 newsrv->onerror = HANA_ONERR_MARKDWN;
4556 else {
4557 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004558 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004559 file, linenum, args[cur_arg], args[cur_arg + 1]);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
4563
4564 cur_arg += 2;
4565 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004566 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4567 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4568 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4569 else {
4570 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4571 file, linenum, args[cur_arg], args[cur_arg + 1]);
4572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
4574 }
4575
4576 cur_arg += 2;
4577 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004578 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4579 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4580 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4581 else {
4582 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4583 file, linenum, args[cur_arg], args[cur_arg + 1]);
4584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
4586 }
4587
4588 cur_arg += 2;
4589 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004590 else if (!strcmp(args[cur_arg], "error-limit")) {
4591 if (!*args[cur_arg + 1]) {
4592 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4593 file, linenum, args[cur_arg]);
4594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
4596 }
4597
4598 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4599
4600 if (newsrv->consecutive_errors_limit <= 0) {
4601 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4602 file, linenum, args[cur_arg]);
4603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004606 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004607 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004608 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004609 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004610 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004611 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004612
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004614 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4615 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004619
Willy Tarreauef9a3602012-12-08 22:29:20 +01004620 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004621 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004622 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004623 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004624 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004626 goto out;
4627 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004628
4629 proto = protocol_by_family(sk->ss_family);
4630 if (!proto || !proto->connect) {
4631 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4632 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004636
Willy Tarreauef9a3602012-12-08 22:29:20 +01004637 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004638
4639 if (port_low != port_high) {
4640 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004641
4642 if (!port_low || !port_high) {
4643 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4644 file, linenum, args[cur_arg], args[cur_arg + 1]);
4645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
4647 }
4648
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004649 if (port_low <= 0 || port_low > 65535 ||
4650 port_high <= 0 || port_high > 65535 ||
4651 port_low > port_high) {
4652 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4653 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004656 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004657 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4658 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4659 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004660 }
4661
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004663 while (*(args[cur_arg])) {
4664 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004665#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4666#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004667 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004668 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4669 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004670 err_code |= ERR_ALERT | ERR_FATAL;
4671 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004672 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004673#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004674 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004675 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004676 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004679 }
4680 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004681 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4682 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004683 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004684 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4685 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004686 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4687 char *name, *end;
4688
4689 name = args[cur_arg+1] + 7;
4690 while (isspace(*name))
4691 name++;
4692
4693 end = name;
4694 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4695 end++;
4696
Willy Tarreauef9a3602012-12-08 22:29:20 +01004697 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4698 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4699 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4700 newsrv->conn_src.bind_hdr_len = end - name;
4701 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4702 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4703 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004704
4705 /* now look for an occurrence number */
4706 while (isspace(*end))
4707 end++;
4708 if (*end == ',') {
4709 end++;
4710 name = end;
4711 if (*end == '-')
4712 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004713 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004714 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004715 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004716 }
4717
Willy Tarreauef9a3602012-12-08 22:29:20 +01004718 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004719 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4720 " occurrences values smaller than %d.\n",
4721 file, linenum, MAX_HDR_HISTORY);
4722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004725 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004726 struct sockaddr_storage *sk;
4727 int port1, port2;
4728
Willy Tarreau902636f2013-03-10 19:44:48 +01004729 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004730 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004731 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004732 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004733 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004734 goto out;
4735 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004736
4737 proto = protocol_by_family(sk->ss_family);
4738 if (!proto || !proto->connect) {
4739 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4740 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004744
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004745 if (port1 != port2) {
4746 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4747 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
4750 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004751 newsrv->conn_src.tproxy_addr = *sk;
4752 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004753 }
4754 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004755#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004756 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004757#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004758 cur_arg += 2;
4759 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004760#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004761 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004762 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004765#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004766 } /* "usesrc" */
4767
4768 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4769#ifdef SO_BINDTODEVICE
4770 if (!*args[cur_arg + 1]) {
4771 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004775 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004776 free(newsrv->conn_src.iface_name);
4777 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4778 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004779 global.last_checks |= LSTCHK_NETADM;
4780#else
4781 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4782 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004785#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004786 cur_arg += 2;
4787 continue;
4788 }
4789 /* this keyword in not an option of "source" */
4790 break;
4791 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004793 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004794 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4795 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004800 static int srv_dumped;
4801 struct srv_kw *kw;
4802 char *err;
4803
4804 kw = srv_find_kw(args[cur_arg]);
4805 if (kw) {
4806 char *err = NULL;
4807 int code;
4808
4809 if (!kw->parse) {
4810 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4811 file, linenum, args[0], args[1], args[cur_arg]);
4812 cur_arg += 1 + kw->skip ;
4813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
4816
4817 if (defsrv && !kw->default_ok) {
4818 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4819 file, linenum, args[0], args[1], args[cur_arg]);
4820 cur_arg += 1 + kw->skip ;
4821 err_code |= ERR_ALERT;
4822 continue;
4823 }
4824
4825 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4826 err_code |= code;
4827
4828 if (code) {
4829 if (err && *err) {
4830 indent_msg(&err, 2);
4831 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4832 }
4833 else
4834 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4835 file, linenum, args[0], args[1], args[cur_arg]);
4836 if (code & ERR_FATAL) {
4837 free(err);
4838 cur_arg += 1 + kw->skip;
4839 goto out;
4840 }
4841 }
4842 free(err);
4843 cur_arg += 1 + kw->skip;
4844 continue;
4845 }
4846
4847 err = NULL;
4848 if (!srv_dumped) {
4849 srv_dump_kws(&err);
4850 indent_msg(&err, 4);
4851 srv_dumped = 1;
4852 }
4853
4854 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4855 file, linenum, args[0], args[1], args[cur_arg],
4856 err ? " Registered keywords :" : "", err ? err : "");
4857 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004858
Willy Tarreau93893792009-07-23 13:19:11 +02004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 }
4862 }
4863
4864 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09004865 int ret;
4866
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004867 if (newsrv->trackit) {
4868 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4869 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004872 }
4873
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004874 /* If neither a port nor an addr was specified and no check transport
4875 * layer is forced, then the transport layer used by the checks is the
4876 * same as for the production traffic. Otherwise we use raw_sock by
4877 * default, unless one is specified.
4878 */
Simon Horman66183002013-02-23 10:16:43 +09004879 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004880#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004881 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004882#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004883 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4884 }
Simon Horman66183002013-02-23 10:16:43 +09004885 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004886 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09004887 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004888
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004889 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004890 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004891
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004892 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004893 /* not yet valid, because no port was set on
4894 * the server either. We'll check if we have
4895 * a known port on the first listener.
4896 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004897 struct listener *l;
4898
4899 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004900 newsrv->check.port = get_host_port(&l->addr);
4901 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004902 break;
4903 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004904 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004905 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4907 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004911
Simon Horman69d29f92013-02-23 15:14:19 +09004912 ret = init_check(&newsrv->check,
4913 curproxy->options2 & PR_O2_CHK_ANY,
4914 file, linenum);
4915 if (ret) {
4916 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004917 goto out;
4918 }
4919
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 newsrv->state |= SRV_CHECKED;
4921 }
4922
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004923 if (!defsrv) {
4924 if (newsrv->state & SRV_BACKUP)
4925 curproxy->srv_bck++;
4926 else
4927 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004928
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004929 newsrv->prev_state = newsrv->state;
4930 }
William Lallemanda73203e2012-03-12 12:48:57 +01004931 }
4932
4933 else if (strcmp(args[0], "unique-id-format") == 0) {
4934 if (!*(args[1])) {
4935 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
4938 }
William Lallemand3203ff42012-11-11 17:30:56 +01004939 if (*(args[2])) {
4940 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
4943 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004944 free(curproxy->conf.uniqueid_format_string);
4945 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004946
Willy Tarreau62a61232013-04-12 18:13:46 +02004947 free(curproxy->conf.uif_file);
4948 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4949 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004950 }
William Lallemanda73203e2012-03-12 12:48:57 +01004951
4952 else if (strcmp(args[0], "unique-id-header") == 0) {
4953 if (!*(args[1])) {
4954 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
4958 free(curproxy->header_unique_id);
4959 curproxy->header_unique_id = strdup(args[1]);
4960 }
4961
William Lallemand723b73a2012-02-08 16:37:49 +01004962 else if (strcmp(args[0], "log-format") == 0) {
4963 if (!*(args[1])) {
4964 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
4967 }
William Lallemand3203ff42012-11-11 17:30:56 +01004968 if (*(args[2])) {
4969 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004973
Willy Tarreau62a61232013-04-12 18:13:46 +02004974 if (curproxy->conf.logformat_string != default_http_log_format &&
4975 curproxy->conf.logformat_string != default_tcp_log_format &&
4976 curproxy->conf.logformat_string != clf_http_log_format)
4977 free(curproxy->conf.logformat_string);
4978 curproxy->conf.logformat_string = strdup(args[1]);
4979
4980 free(curproxy->conf.lfs_file);
4981 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4982 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004983
4984 /* get a chance to improve log-format error reporting by
4985 * reporting the correct line-number when possible.
4986 */
4987 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4988 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4989 file, linenum, curproxy->id);
4990 err_code |= ERR_WARN;
4991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 }
William Lallemand723b73a2012-02-08 16:37:49 +01004993
William Lallemand0f99e342011-10-12 17:50:54 +02004994 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4995 /* delete previous herited or defined syslog servers */
4996 struct logsrv *back;
4997
4998 if (*(args[1]) != 0) {
4999 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
5002 }
5003
William Lallemand723b73a2012-02-08 16:37:49 +01005004 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5005 LIST_DEL(&tmplogsrv->list);
5006 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005007 }
5008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005010 struct logsrv *logsrv;
5011
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005013 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005014 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005015 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005016 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005017 LIST_INIT(&node->list);
5018 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
5021 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005022 struct sockaddr_storage *sk;
5023 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005024
5025 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026
William Lallemand0f99e342011-10-12 17:50:54 +02005027 logsrv->facility = get_log_facility(args[2]);
5028 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
5034
William Lallemand0f99e342011-10-12 17:50:54 +02005035 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005037 logsrv->level = get_log_level(args[3]);
5038 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
5042
Willy Tarreaubaaee002006-06-26 02:48:02 +02005043 }
5044 }
5045
William Lallemand0f99e342011-10-12 17:50:54 +02005046 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005047 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005048 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005049 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005050 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005054 }
5055 }
5056
Willy Tarreau902636f2013-03-10 19:44:48 +01005057 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005058 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005059 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005060 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005061 goto out;
5062 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005063
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005064 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005065
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005066 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005067 if (port1 != port2) {
5068 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5069 file, linenum, args[0], args[1]);
5070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
5072 }
5073
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005074 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005075 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
William Lallemand0f99e342011-10-12 17:50:54 +02005077
5078 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 }
5080 else {
5081 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5082 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 }
5086 }
5087 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005088 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005089 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005090 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005091 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005092
Willy Tarreau977b8e42006-12-29 14:19:17 +01005093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005095
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005097 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5098 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005102
5103 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005104 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5105 free(curproxy->conn_src.iface_name);
5106 curproxy->conn_src.iface_name = NULL;
5107 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005108
Willy Tarreau902636f2013-03-10 19:44:48 +01005109 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005110 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005111 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005112 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005113 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005114 goto out;
5115 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005116
5117 proto = protocol_by_family(sk->ss_family);
5118 if (!proto || !proto->connect) {
5119 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005120 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
5123 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005124
5125 if (port1 != port2) {
5126 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5127 file, linenum, args[0], args[1]);
5128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
5131
Willy Tarreauef9a3602012-12-08 22:29:20 +01005132 curproxy->conn_src.source_addr = *sk;
5133 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005134
5135 cur_arg = 2;
5136 while (*(args[cur_arg])) {
5137 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005138#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5139#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005140 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005141 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5142 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005145 }
5146#endif
5147 if (!*args[cur_arg + 1]) {
5148 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5149 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005152 }
5153
5154 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005155 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5156 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005157 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005158 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5159 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005160 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5161 char *name, *end;
5162
5163 name = args[cur_arg+1] + 7;
5164 while (isspace(*name))
5165 name++;
5166
5167 end = name;
5168 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5169 end++;
5170
Willy Tarreauef9a3602012-12-08 22:29:20 +01005171 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5172 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5173 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5174 curproxy->conn_src.bind_hdr_len = end - name;
5175 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5176 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5177 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005178
5179 /* now look for an occurrence number */
5180 while (isspace(*end))
5181 end++;
5182 if (*end == ',') {
5183 end++;
5184 name = end;
5185 if (*end == '-')
5186 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005187 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005188 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005189 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005190 }
5191
Willy Tarreauef9a3602012-12-08 22:29:20 +01005192 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005193 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5194 " occurrences values smaller than %d.\n",
5195 file, linenum, MAX_HDR_HISTORY);
5196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
5198 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005199 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005200 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005201
Willy Tarreau902636f2013-03-10 19:44:48 +01005202 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005203 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005204 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005205 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005206 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005207 goto out;
5208 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005209
5210 proto = protocol_by_family(sk->ss_family);
5211 if (!proto || !proto->connect) {
5212 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5213 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
5216 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005217
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005218 if (port1 != port2) {
5219 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5220 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005224 curproxy->conn_src.tproxy_addr = *sk;
5225 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005226 }
5227 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005228#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005229 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005230#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005231#else /* no TPROXY support */
5232 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005233 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005236#endif
5237 cur_arg += 2;
5238 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005239 }
5240
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005241 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5242#ifdef SO_BINDTODEVICE
5243 if (!*args[cur_arg + 1]) {
5244 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005248 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005249 free(curproxy->conn_src.iface_name);
5250 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5251 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005252 global.last_checks |= LSTCHK_NETADM;
5253#else
5254 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5255 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005258#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005259 cur_arg += 2;
5260 continue;
5261 }
5262 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005263 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005268 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5269 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5270 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5277 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005278 err_code |= ERR_ALERT | ERR_FATAL;
5279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281
5282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005283 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005284 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 }
5288 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005290 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005291 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294 }
5295 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005296 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005297 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005298 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005299 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 }
5302 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005304 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005305 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 }
5309 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005310 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005311 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005312 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005313 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005316 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005318 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005319 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005320 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005321 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005322 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005323 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005324 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005325 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005326 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005327 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005328 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005329 }
5330 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005331 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005332 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005333 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005334 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005335 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005338 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005344
5345 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005346 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005347 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005348 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 }
5351 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005353 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005354 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 }
5358 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005360 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
5365 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005367 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 }
5372 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005373 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005374 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005375 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005376 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005379 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005380 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005381 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005382 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005383 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005384 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005387 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005388
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 if (curproxy == &defproxy) {
5390 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005394 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005395 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 if (*(args[1]) == 0) {
5398 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005402
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005403 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005404 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5405 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5406 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
5409 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005410 err_code |= warnif_cond_conflicts(cond,
5411 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5412 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005413 }
5414 else if (*args[2]) {
5415 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5416 file, linenum, args[0], args[2]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005421 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005422 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005423 wl->s = strdup(args[1]);
5424 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005425 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
5427 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005428 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005429 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5430 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005434
Willy Tarreauade5ec42010-01-28 19:33:49 +01005435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005436 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005437 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005440 }
5441 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005442 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005443 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005444 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005445 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 }
5448 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005449 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005450 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005451 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005452 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 }
5455 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005456 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
5462
Willy Tarreauade5ec42010-01-28 19:33:49 +01005463 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005464 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005465 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005466 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 }
5469 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005470 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005471 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005472 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005473 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 }
5476 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005477 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005478 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005479 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005480 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 }
5483 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005484 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005485
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 if (curproxy == &defproxy) {
5487 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005491 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005492 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 if (*(args[1]) == 0) {
5495 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005498 }
5499
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005500 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005501 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5502 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5503 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005504 err_code |= ERR_ALERT | ERR_FATAL;
5505 goto out;
5506 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005507 err_code |= warnif_cond_conflicts(cond,
5508 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5509 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005510 }
5511 else if (*args[2]) {
5512 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5513 file, linenum, args[0], args[2]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 }
5517
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005518 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005519 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005520 wl->s = strdup(args[1]);
5521 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 }
5523 else if (!strcmp(args[0], "errorloc") ||
5524 !strcmp(args[0], "errorloc302") ||
5525 !strcmp(args[0], "errorloc303")) { /* error location */
5526 int errnum, errlen;
5527 char *err;
5528
Willy Tarreau977b8e42006-12-29 14:19:17 +01005529 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005530 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005531
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005533 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 }
5537
5538 errnum = atol(args[1]);
5539 if (!strcmp(args[0], "errorloc303")) {
5540 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5541 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5542 } else {
5543 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5544 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5545 }
5546
Willy Tarreau0f772532006-12-23 20:51:41 +01005547 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5548 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005549 chunk_destroy(&curproxy->errmsg[rc]);
5550 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005551 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005554
5555 if (rc >= HTTP_ERR_SIZE) {
5556 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5557 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 free(err);
5559 }
5560 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005561 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5562 int errnum, errlen, fd;
5563 char *err;
5564 struct stat stat;
5565
5566 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005568
5569 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005570 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005573 }
5574
5575 fd = open(args[2], O_RDONLY);
5576 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5577 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5578 file, linenum, args[2], args[1]);
5579 if (fd >= 0)
5580 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005583 }
5584
Willy Tarreau27a674e2009-08-17 07:23:33 +02005585 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005586 errlen = stat.st_size;
5587 } else {
5588 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005589 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005590 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005591 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005592 }
5593
5594 err = malloc(errlen); /* malloc() must succeed during parsing */
5595 errnum = read(fd, err, errlen);
5596 if (errnum != errlen) {
5597 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5598 file, linenum, args[2], args[1]);
5599 close(fd);
5600 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005603 }
5604 close(fd);
5605
5606 errnum = atol(args[1]);
5607 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5608 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005609 chunk_destroy(&curproxy->errmsg[rc]);
5610 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005611 break;
5612 }
5613 }
5614
5615 if (rc >= HTTP_ERR_SIZE) {
5616 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5617 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005618 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005619 free(err);
5620 }
5621 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005622 else if (!strcmp(args[0], "compression")) {
5623 struct comp *comp;
5624 if (curproxy->comp == NULL) {
5625 comp = calloc(1, sizeof(struct comp));
5626 curproxy->comp = comp;
5627 } else {
5628 comp = curproxy->comp;
5629 }
5630
5631 if (!strcmp(args[1], "algo")) {
5632 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005633 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005634
William Lallemand82fe75c2012-10-23 10:25:10 +02005635 cur_arg = 2;
5636 if (!*args[cur_arg]) {
5637 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5638 file, linenum, args[0]);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
5642 while (*(args[cur_arg])) {
5643 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5644 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5645 file, linenum, args[0], args[cur_arg]);
5646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
William Lallemand552df672012-11-07 13:21:47 +01005649 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5650 curproxy->comp->algos->end(&ctx);
5651 } else {
5652 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5653 file, linenum, args[0], args[cur_arg]);
5654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
5656 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005657 cur_arg ++;
5658 continue;
5659 }
5660 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005661 else if (!strcmp(args[1], "offload")) {
5662 comp->offload = 1;
5663 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005664 else if (!strcmp(args[1], "type")) {
5665 int cur_arg;
5666 cur_arg = 2;
5667 if (!*args[cur_arg]) {
5668 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5669 file, linenum, args[0]);
5670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
5672 }
5673 while (*(args[cur_arg])) {
5674 comp_append_type(comp, args[cur_arg]);
5675 cur_arg ++;
5676 continue;
5677 }
5678 }
5679 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005680 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005681 file, linenum, args[0]);
5682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
5684 }
5685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005687 struct cfg_kw_list *kwl;
5688 int index;
5689
5690 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5691 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5692 if (kwl->kw[index].section != CFG_LISTEN)
5693 continue;
5694 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5695 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005696 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005697 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005698 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005701 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005702 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005703 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005704 err_code |= ERR_WARN;
5705 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005706 }
Willy Tarreau93893792009-07-23 13:19:11 +02005707 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005708 }
5709 }
5710 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005711
Willy Tarreau6daf3432008-01-22 16:44:08 +01005712 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 }
Willy Tarreau93893792009-07-23 13:19:11 +02005716 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005717 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005718 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719}
5720
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005721int
5722cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5723{
5724
5725 int err_code = 0;
5726 const char *err;
5727
5728 if (!strcmp(args[0], "userlist")) { /* new userlist */
5729 struct userlist *newul;
5730
5731 if (!*args[1]) {
5732 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5733 file, linenum, args[0]);
5734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
5736 }
5737
5738 err = invalid_char(args[1]);
5739 if (err) {
5740 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5741 file, linenum, *err, args[0], args[1]);
5742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
5744 }
5745
5746 for (newul = userlist; newul; newul = newul->next)
5747 if (!strcmp(newul->name, args[1])) {
5748 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5749 file, linenum, args[1]);
5750 err_code |= ERR_WARN;
5751 goto out;
5752 }
5753
5754 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5755 if (!newul) {
5756 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5757 err_code |= ERR_ALERT | ERR_ABORT;
5758 goto out;
5759 }
5760
5761 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5762 newul->name = strdup(args[1]);
5763
5764 if (!newul->groupusers | !newul->name) {
5765 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5766 err_code |= ERR_ALERT | ERR_ABORT;
5767 goto out;
5768 }
5769
5770 newul->next = userlist;
5771 userlist = newul;
5772
5773 } else if (!strcmp(args[0], "group")) { /* new group */
5774 int cur_arg, i;
5775 const char *err;
5776
5777 if (!*args[1]) {
5778 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5779 file, linenum, args[0]);
5780 err_code |= ERR_ALERT | ERR_FATAL;
5781 goto out;
5782 }
5783
5784 err = invalid_char(args[1]);
5785 if (err) {
5786 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5787 file, linenum, *err, args[0], args[1]);
5788 err_code |= ERR_ALERT | ERR_FATAL;
5789 goto out;
5790 }
5791
5792 for(i = 0; i < userlist->grpcnt; i++)
5793 if (!strcmp(userlist->groups[i], args[1])) {
5794 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5795 file, linenum, args[1], userlist->name);
5796 err_code |= ERR_ALERT;
5797 goto out;
5798 }
5799
5800 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5801 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5802 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5803 err_code |= ERR_ALERT | ERR_FATAL;
5804 goto out;
5805 }
5806
5807 cur_arg = 2;
5808
5809 while (*args[cur_arg]) {
5810 if (!strcmp(args[cur_arg], "users")) {
5811 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5812 cur_arg += 2;
5813 continue;
5814 } else {
5815 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5816 file, linenum, args[0]);
5817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
5819 }
5820 }
5821
5822 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5823 } else if (!strcmp(args[0], "user")) { /* new user */
5824 struct auth_users *newuser;
5825 int cur_arg;
5826
5827 if (!*args[1]) {
5828 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5829 file, linenum, args[0]);
5830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
5832 }
5833
5834 for (newuser = userlist->users; newuser; newuser = newuser->next)
5835 if (!strcmp(newuser->user, args[1])) {
5836 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5837 file, linenum, args[1], userlist->name);
5838 err_code |= ERR_ALERT;
5839 goto out;
5840 }
5841
5842 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5843 if (!newuser) {
5844 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5845 err_code |= ERR_ALERT | ERR_ABORT;
5846 goto out;
5847 }
5848
5849 newuser->user = strdup(args[1]);
5850
5851 newuser->next = userlist->users;
5852 userlist->users = newuser;
5853
5854 cur_arg = 2;
5855
5856 while (*args[cur_arg]) {
5857 if (!strcmp(args[cur_arg], "password")) {
5858#ifndef CONFIG_HAP_CRYPT
5859 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5860 file, linenum);
5861 err_code |= ERR_ALERT;
5862#endif
5863 newuser->pass = strdup(args[cur_arg + 1]);
5864 cur_arg += 2;
5865 continue;
5866 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5867 newuser->pass = strdup(args[cur_arg + 1]);
5868 newuser->flags |= AU_O_INSECURE;
5869 cur_arg += 2;
5870 continue;
5871 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005872 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005873 cur_arg += 2;
5874 continue;
5875 } else {
5876 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5877 file, linenum, args[0]);
5878 err_code |= ERR_ALERT | ERR_FATAL;
5879 goto out;
5880 }
5881 }
5882 } else {
5883 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5884 err_code |= ERR_ALERT | ERR_FATAL;
5885 }
5886
5887out:
5888 return err_code;
5889}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005890
5891/*
5892 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005893 * Returns the error code, 0 if OK, or any combination of :
5894 * - ERR_ABORT: must abort ASAP
5895 * - ERR_FATAL: we can continue parsing but not start the service
5896 * - ERR_WARN: a warning has been emitted
5897 * - ERR_ALERT: an alert has been emitted
5898 * Only the two first ones can stop processing, the two others are just
5899 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005900 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005901int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005903 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005904 FILE *f;
5905 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005907 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908
Willy Tarreaubaaee002006-06-26 02:48:02 +02005909 if ((f=fopen(file,"r")) == NULL)
5910 return -1;
5911
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005912 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005913 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005914 char *end;
5915 char *args[MAX_LINE_ARGS + 1];
5916 char *line = thisline;
5917
Willy Tarreaubaaee002006-06-26 02:48:02 +02005918 linenum++;
5919
5920 end = line + strlen(line);
5921
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005922 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5923 /* Check if we reached the limit and the last char is not \n.
5924 * Watch out for the last line without the terminating '\n'!
5925 */
5926 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005927 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005928 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005929 }
5930
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005932 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 line++;
5934
5935 arg = 0;
5936 args[arg] = line;
5937
5938 while (*line && arg < MAX_LINE_ARGS) {
5939 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5940 * C equivalent value. Other combinations left unchanged (eg: \1).
5941 */
5942 if (*line == '\\') {
5943 int skip = 0;
5944 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5945 *line = line[1];
5946 skip = 1;
5947 }
5948 else if (line[1] == 'r') {
5949 *line = '\r';
5950 skip = 1;
5951 }
5952 else if (line[1] == 'n') {
5953 *line = '\n';
5954 skip = 1;
5955 }
5956 else if (line[1] == 't') {
5957 *line = '\t';
5958 skip = 1;
5959 }
5960 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005961 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962 unsigned char hex1, hex2;
5963 hex1 = toupper(line[2]) - '0';
5964 hex2 = toupper(line[3]) - '0';
5965 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5966 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5967 *line = (hex1<<4) + hex2;
5968 skip = 3;
5969 }
5970 else {
5971 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005972 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 }
5974 }
5975 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005976 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 end -= skip;
5978 }
5979 line++;
5980 }
5981 else if (*line == '#' || *line == '\n' || *line == '\r') {
5982 /* end of string, end of loop */
5983 *line = 0;
5984 break;
5985 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005986 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005988 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005989 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 line++;
5991 args[++arg] = line;
5992 }
5993 else {
5994 line++;
5995 }
5996 }
5997
5998 /* empty line */
5999 if (!**args)
6000 continue;
6001
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006002 if (*line) {
6003 /* we had to stop due to too many args.
6004 * Let's terminate the string, print the offending part then cut the
6005 * last arg.
6006 */
6007 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6008 line++;
6009 *line = '\0';
6010
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006011 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006012 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006013 err_code |= ERR_ALERT | ERR_FATAL;
6014 args[arg] = line;
6015 }
6016
Willy Tarreau540abe42007-05-02 20:50:16 +02006017 /* zero out remaining args and ensure that at least one entry
6018 * is zeroed out.
6019 */
6020 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 args[arg] = line;
6022 }
6023
Willy Tarreau3842f002009-06-14 11:39:52 +02006024 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006025 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006026 char *tmp;
6027
Willy Tarreau3842f002009-06-14 11:39:52 +02006028 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006029 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006030 for (arg=0; *args[arg+1]; arg++)
6031 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006032 *tmp = '\0'; // fix the next arg to \0
6033 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006034 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006035 else if (!strcmp(args[0], "default")) {
6036 kwm = KWM_DEF;
6037 for (arg=0; *args[arg+1]; arg++)
6038 args[arg] = args[arg+1]; // shift args after inversion
6039 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006040
William Lallemand0f99e342011-10-12 17:50:54 +02006041 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6042 strcmp(args[0], "log") != 0) {
6043 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006044 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006045 }
6046
Willy Tarreau977b8e42006-12-29 14:19:17 +01006047 if (!strcmp(args[0], "listen") ||
6048 !strcmp(args[0], "frontend") ||
6049 !strcmp(args[0], "backend") ||
6050 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006051 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006053 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006054 cursection = strdup(args[0]);
6055 }
6056 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006058 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006059 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006060 }
6061 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006062 confsect = CFG_USERLIST;
6063 free(cursection);
6064 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006065 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006066 else if (!strcmp(args[0], "peers")) {
6067 confsect = CFG_PEERS;
6068 free(cursection);
6069 cursection = strdup(args[0]);
6070 }
6071
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072 /* else it's a section keyword */
6073
6074 switch (confsect) {
6075 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006076 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077 break;
6078 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006079 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006080 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006081 case CFG_USERLIST:
6082 err_code |= cfg_parse_users(file, linenum, args, kwm);
6083 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006084 case CFG_PEERS:
6085 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6086 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006087 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006088 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006089 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006090 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006091
6092 if (err_code & ERR_ABORT)
6093 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006094 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006095 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006096 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006097 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006098 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006099}
6100
Willy Tarreaubb925012009-07-23 13:36:36 +02006101/*
6102 * Returns the error code, 0 if OK, or any combination of :
6103 * - ERR_ABORT: must abort ASAP
6104 * - ERR_FATAL: we can continue parsing but not start the service
6105 * - ERR_WARN: a warning has been emitted
6106 * - ERR_ALERT: an alert has been emitted
6107 * Only the two first ones can stop processing, the two others are just
6108 * indicators.
6109 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006110int check_config_validity()
6111{
6112 int cfgerr = 0;
6113 struct proxy *curproxy = NULL;
6114 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006115 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006116 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006117 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006118 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006120 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006121 /*
6122 * Now, check for the integrity of all that we have collected.
6123 */
6124
6125 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006126 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127
Willy Tarreau193b8c62012-11-22 00:17:38 +01006128 if (!global.tune.max_http_hdr)
6129 global.tune.max_http_hdr = MAX_HTTP_HDR;
6130
6131 if (!global.tune.cookie_len)
6132 global.tune.cookie_len = CAPTURE_LEN;
6133
6134 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6135
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006136 /* first, we will invert the proxy list order */
6137 curproxy = NULL;
6138 while (proxy) {
6139 struct proxy *next;
6140
6141 next = proxy->next;
6142 proxy->next = curproxy;
6143 curproxy = proxy;
6144 if (!next)
6145 break;
6146 proxy = next;
6147 }
6148
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006150 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006151 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006152 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006153 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006154 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006155 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006156 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006157
Willy Tarreau050536d2012-10-04 08:47:34 +02006158 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006159 /* proxy ID not set, use automatic numbering with first
6160 * spare entry starting with next_pxid.
6161 */
6162 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6163 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6164 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006165 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006166 next_pxid++;
6167
Willy Tarreau55ea7572007-06-17 19:56:27 +02006168
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006170 /* ensure we don't keep listeners uselessly bound */
6171 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 curproxy = curproxy->next;
6173 continue;
6174 }
6175
Willy Tarreau16a21472012-11-19 12:39:59 +01006176 /* number of processes this proxy is bound to */
6177 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6178
Willy Tarreauff01a212009-03-15 13:46:16 +01006179 switch (curproxy->mode) {
6180 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006181 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006182 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006183 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6184 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006185 cfgerr++;
6186 }
6187
6188 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006189 Warning("config : servers will be ignored for %s '%s'.\n",
6190 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006191 break;
6192
6193 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006194 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006195 break;
6196
6197 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006198 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006199 break;
6200 }
6201
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006202 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006203 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006204 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006205 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6206 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006207 cfgerr++;
6208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006210 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006211 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6212 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006213 cfgerr++;
6214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006216 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006217 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6218 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006219 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006220 }
6221 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006222 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006223 /* If no LB algo is set in a backend, and we're not in
6224 * transparent mode, dispatch mode nor proxy mode, we
6225 * want to use balance roundrobin by default.
6226 */
6227 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6228 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 }
6230 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006231
Willy Tarreau1620ec32011-08-06 17:05:02 +02006232 if (curproxy->options & PR_O_DISPATCH)
6233 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6234 else if (curproxy->options & PR_O_HTTP_PROXY)
6235 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6236 else if (curproxy->options & PR_O_TRANSP)
6237 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006238
Willy Tarreau1620ec32011-08-06 17:05:02 +02006239 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6240 if (curproxy->options & PR_O_DISABLE404) {
6241 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6242 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6243 err_code |= ERR_WARN;
6244 curproxy->options &= ~PR_O_DISABLE404;
6245 }
6246 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6247 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6248 "send-state", proxy_type_str(curproxy), curproxy->id);
6249 err_code |= ERR_WARN;
6250 curproxy->options &= ~PR_O2_CHK_SNDST;
6251 }
Willy Tarreauef781042010-01-27 11:53:01 +01006252 }
6253
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006254 /* if a default backend was specified, let's find it */
6255 if (curproxy->defbe.name) {
6256 struct proxy *target;
6257
Alex Williams96532db2009-11-01 21:27:13 -05006258 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006259 if (!target) {
6260 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6261 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006262 cfgerr++;
6263 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006264 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6265 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006266 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006267 } else {
6268 free(curproxy->defbe.name);
6269 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006270 /* we force the backend to be present on at least all of
6271 * the frontend's processes.
6272 */
6273 target->bind_proc = curproxy->bind_proc ?
6274 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006275
6276 /* Emit a warning if this proxy also has some servers */
6277 if (curproxy->srv) {
6278 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6279 curproxy->id);
6280 err_code |= ERR_WARN;
6281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 }
6283 }
6284
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006285 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006286 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6287 /* map jump target for ACT_SETBE in req_rep chain */
6288 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006289 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006290 struct proxy *target;
6291
Willy Tarreaua496b602006-12-17 23:15:24 +01006292 if (exp->action != ACT_SETBE)
6293 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006294
Alex Williams96532db2009-11-01 21:27:13 -05006295 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006296 if (!target) {
6297 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6298 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006299 cfgerr++;
6300 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006301 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6302 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006303 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006304 } else {
6305 free((void *)exp->replace);
6306 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006307 /* we force the backend to be present on at least all of
6308 * the frontend's processes.
6309 */
6310 target->bind_proc = curproxy->bind_proc ?
6311 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006312 }
6313 }
6314 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006315
6316 /* find the target proxy for 'use_backend' rules */
6317 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006318 struct proxy *target;
6319
Alex Williams96532db2009-11-01 21:27:13 -05006320 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006321
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006322 if (!target) {
6323 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6324 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006325 cfgerr++;
6326 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006327 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6328 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006329 cfgerr++;
6330 } else {
6331 free((void *)rule->be.name);
6332 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006333 /* we force the backend to be present on at least all of
6334 * the frontend's processes.
6335 */
6336 target->bind_proc = curproxy->bind_proc ?
6337 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006338 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006339 }
6340
6341 /* find the target proxy for 'use_backend' rules */
6342 list_for_each_entry(srule, &curproxy->server_rules, list) {
6343 struct server *target = findserver(curproxy, srule->srv.name);
6344
6345 if (!target) {
6346 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6347 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6348 cfgerr++;
6349 continue;
6350 }
6351 free((void *)srule->srv.name);
6352 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006353 }
6354
Emeric Brunb982a3d2010-01-04 15:45:53 +01006355 /* find the target table for 'stick' rules */
6356 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6357 struct proxy *target;
6358
Emeric Brun1d33b292010-01-04 15:47:17 +01006359 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6360 if (mrule->flags & STK_IS_STORE)
6361 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6362
Emeric Brunb982a3d2010-01-04 15:45:53 +01006363 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006364 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006365 else
6366 target = curproxy;
6367
6368 if (!target) {
6369 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6370 curproxy->id, mrule->table.name);
6371 cfgerr++;
6372 }
6373 else if (target->table.size == 0) {
6374 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6375 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6376 cfgerr++;
6377 }
Willy Tarreau12785782012-04-27 21:37:17 +02006378 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6379 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006380 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6381 cfgerr++;
6382 }
6383 else {
6384 free((void *)mrule->table.name);
6385 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006386 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006387 }
6388 }
6389
6390 /* find the target table for 'store response' rules */
6391 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6392 struct proxy *target;
6393
Emeric Brun1d33b292010-01-04 15:47:17 +01006394 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6395
Emeric Brunb982a3d2010-01-04 15:45:53 +01006396 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006397 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006398 else
6399 target = curproxy;
6400
6401 if (!target) {
6402 Alert("Proxy '%s': unable to find store table '%s'.\n",
6403 curproxy->id, mrule->table.name);
6404 cfgerr++;
6405 }
6406 else if (target->table.size == 0) {
6407 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6408 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6409 cfgerr++;
6410 }
Willy Tarreau12785782012-04-27 21:37:17 +02006411 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6412 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006413 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6414 cfgerr++;
6415 }
6416 else {
6417 free((void *)mrule->table.name);
6418 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006419 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006420 }
6421 }
6422
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006423 /* find the target table for 'tcp-request' layer 4 rules */
6424 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6425 struct proxy *target;
6426
Willy Tarreaub4c84932013-07-23 19:15:30 +02006427 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006428 continue;
6429
6430 if (trule->act_prm.trk_ctr.table.n)
6431 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6432 else
6433 target = curproxy;
6434
6435 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006436 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6437 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006438 1 + tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006439 cfgerr++;
6440 }
6441 else if (target->table.size == 0) {
6442 Alert("Proxy '%s': table '%s' used but not configured.\n",
6443 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6444 cfgerr++;
6445 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006446 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6447 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6448 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 +02006449 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006450 cfgerr++;
6451 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006452 else {
6453 free(trule->act_prm.trk_ctr.table.n);
6454 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006455 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006456 * to pass a list of counters to track and allocate them right here using
6457 * stktable_alloc_data_type().
6458 */
6459 }
6460 }
6461
Willy Tarreaud1f96522010-08-03 19:34:32 +02006462 /* find the target table for 'tcp-request' layer 6 rules */
6463 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6464 struct proxy *target;
6465
Willy Tarreaub4c84932013-07-23 19:15:30 +02006466 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006467 continue;
6468
6469 if (trule->act_prm.trk_ctr.table.n)
6470 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6471 else
6472 target = curproxy;
6473
6474 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006475 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6476 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006477 1 + tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006478 cfgerr++;
6479 }
6480 else if (target->table.size == 0) {
6481 Alert("Proxy '%s': table '%s' used but not configured.\n",
6482 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6483 cfgerr++;
6484 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006485 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6486 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6487 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 +02006488 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006489 cfgerr++;
6490 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006491 else {
6492 free(trule->act_prm.trk_ctr.table.n);
6493 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006494 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006495 * to pass a list of counters to track and allocate them right here using
6496 * stktable_alloc_data_type().
6497 */
6498 }
6499 }
6500
Emeric Brun32da3c42010-09-23 18:39:19 +02006501 if (curproxy->table.peers.name) {
6502 struct peers *curpeers = peers;
6503
6504 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6505 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6506 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006507 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006508 break;
6509 }
6510 }
6511
6512 if (!curpeers) {
6513 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6514 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006515 free((void *)curproxy->table.peers.name);
6516 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006517 cfgerr++;
6518 }
6519 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006520 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6521 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006522 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006523 cfgerr++;
6524 }
6525 }
6526
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006527 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006528 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006529 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6530 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6531 "proxy", curproxy->id);
6532 cfgerr++;
6533 goto out_uri_auth_compat;
6534 }
6535
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006536 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006537 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006538 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006539 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006540
Willy Tarreau95fa4692010-02-01 13:05:50 +01006541 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6542 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006543
6544 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006545 uri_auth_compat_req[i++] = "realm";
6546 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6547 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006548
Willy Tarreau95fa4692010-02-01 13:05:50 +01006549 uri_auth_compat_req[i++] = "unless";
6550 uri_auth_compat_req[i++] = "{";
6551 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6552 uri_auth_compat_req[i++] = "}";
6553 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006554
Willy Tarreauff011f22011-01-06 17:51:27 +01006555 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6556 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006557 cfgerr++;
6558 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006559 }
6560
Willy Tarreauff011f22011-01-06 17:51:27 +01006561 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006562
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006563 if (curproxy->uri_auth->auth_realm) {
6564 free(curproxy->uri_auth->auth_realm);
6565 curproxy->uri_auth->auth_realm = NULL;
6566 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006567
6568 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006569 }
6570out_uri_auth_compat:
6571
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006572 /* compile the log format */
6573 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006574 if (curproxy->conf.logformat_string != default_http_log_format &&
6575 curproxy->conf.logformat_string != default_tcp_log_format &&
6576 curproxy->conf.logformat_string != clf_http_log_format)
6577 free(curproxy->conf.logformat_string);
6578 curproxy->conf.logformat_string = NULL;
6579 free(curproxy->conf.lfs_file);
6580 curproxy->conf.lfs_file = NULL;
6581 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006582 }
6583
Willy Tarreau62a61232013-04-12 18:13:46 +02006584 if (curproxy->conf.logformat_string) {
6585 curproxy->conf.args.ctx = ARGC_LOG;
6586 curproxy->conf.args.file = curproxy->conf.lfs_file;
6587 curproxy->conf.args.line = curproxy->conf.lfs_line;
6588 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006589 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006590 curproxy->conf.args.file = NULL;
6591 curproxy->conf.args.line = 0;
6592 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006593
Willy Tarreau62a61232013-04-12 18:13:46 +02006594 if (curproxy->conf.uniqueid_format_string) {
6595 curproxy->conf.args.ctx = ARGC_UIF;
6596 curproxy->conf.args.file = curproxy->conf.uif_file;
6597 curproxy->conf.args.line = curproxy->conf.uif_line;
6598 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006599 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006600 curproxy->conf.args.file = NULL;
6601 curproxy->conf.args.line = 0;
6602 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006603
6604 /* only now we can check if some args remain unresolved */
6605 cfgerr += smp_resolve_args(curproxy);
6606 if (!cfgerr)
6607 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006608
Willy Tarreau2738a142006-07-08 17:28:09 +02006609 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006610 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006611 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006612 (!curproxy->timeout.connect ||
6613 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006614 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006615 " | While not properly invalid, you will certainly encounter various problems\n"
6616 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006617 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006618 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006619 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006620 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006621
Willy Tarreau1fa31262007-12-03 00:36:16 +01006622 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6623 * We must still support older configurations, so let's find out whether those
6624 * parameters have been set or must be copied from contimeouts.
6625 */
6626 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006627 if (!curproxy->timeout.tarpit ||
6628 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006629 /* tarpit timeout not set. We search in the following order:
6630 * default.tarpit, curr.connect, default.connect.
6631 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006632 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006633 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006634 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006635 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006636 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006637 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006638 }
6639 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006640 (!curproxy->timeout.queue ||
6641 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006642 /* queue timeout not set. We search in the following order:
6643 * default.queue, curr.connect, default.connect.
6644 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006645 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006646 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006647 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006648 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006649 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006650 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006651 }
6652 }
6653
Willy Tarreau1620ec32011-08-06 17:05:02 +02006654 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006655 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6656 curproxy->check_req = (char *)malloc(curproxy->check_len);
6657 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006658 }
6659
Willy Tarreau193b8c62012-11-22 00:17:38 +01006660 /* ensure that cookie capture length is not too large */
6661 if (curproxy->capture_len >= global.tune.cookie_len) {
6662 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6663 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6664 err_code |= ERR_WARN;
6665 curproxy->capture_len = global.tune.cookie_len - 1;
6666 }
6667
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006668 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006669 if (curproxy->nb_req_cap) {
6670 if (curproxy->mode == PR_MODE_HTTP) {
6671 curproxy->req_cap_pool = create_pool("ptrcap",
6672 curproxy->nb_req_cap * sizeof(char *),
6673 MEM_F_SHARED);
6674 } else {
6675 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6676 proxy_type_str(curproxy), curproxy->id);
6677 err_code |= ERR_WARN;
6678 curproxy->to_log &= ~LW_REQHDR;
6679 curproxy->nb_req_cap = 0;
6680 }
6681 }
6682
6683 if (curproxy->nb_rsp_cap) {
6684 if (curproxy->mode == PR_MODE_HTTP) {
6685 curproxy->rsp_cap_pool = create_pool("ptrcap",
6686 curproxy->nb_rsp_cap * sizeof(char *),
6687 MEM_F_SHARED);
6688 } else {
6689 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6690 proxy_type_str(curproxy), curproxy->id);
6691 err_code |= ERR_WARN;
6692 curproxy->to_log &= ~LW_REQHDR;
6693 curproxy->nb_rsp_cap = 0;
6694 }
6695 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006696
Willy Tarreaubaaee002006-06-26 02:48:02 +02006697 /* first, we will invert the servers list order */
6698 newsrv = NULL;
6699 while (curproxy->srv) {
6700 struct server *next;
6701
6702 next = curproxy->srv->next;
6703 curproxy->srv->next = newsrv;
6704 newsrv = curproxy->srv;
6705 if (!next)
6706 break;
6707 curproxy->srv = next;
6708 }
6709
Willy Tarreaudd701652010-05-25 23:03:02 +02006710 /* assign automatic UIDs to servers which don't have one yet */
6711 next_id = 1;
6712 newsrv = curproxy->srv;
6713 while (newsrv != NULL) {
6714 if (!newsrv->puid) {
6715 /* server ID not set, use automatic numbering with first
6716 * spare entry starting with next_svid.
6717 */
6718 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6719 newsrv->conf.id.key = newsrv->puid = next_id;
6720 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6721 }
6722 next_id++;
6723 newsrv = newsrv->next;
6724 }
6725
Willy Tarreau20697042007-11-15 23:26:18 +01006726 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006727 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006728
Willy Tarreau62c3be22012-01-20 13:12:32 +01006729 /*
6730 * If this server supports a maxconn parameter, it needs a dedicated
6731 * tasks to fill the emptied slots when a connection leaves.
6732 * Also, resolve deferred tracking dependency if needed.
6733 */
6734 newsrv = curproxy->srv;
6735 while (newsrv != NULL) {
6736 if (newsrv->minconn > newsrv->maxconn) {
6737 /* Only 'minconn' was specified, or it was higher than or equal
6738 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6739 * this will avoid further useless expensive computations.
6740 */
6741 newsrv->maxconn = newsrv->minconn;
6742 } else if (newsrv->maxconn && !newsrv->minconn) {
6743 /* minconn was not specified, so we set it to maxconn */
6744 newsrv->minconn = newsrv->maxconn;
6745 }
6746
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006747#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006748 if (newsrv->use_ssl || newsrv->check.use_ssl)
6749 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006750#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006751
Willy Tarreau62c3be22012-01-20 13:12:32 +01006752 if (newsrv->trackit) {
6753 struct proxy *px;
6754 struct server *srv;
6755 char *pname, *sname;
6756
6757 pname = newsrv->trackit;
6758 sname = strrchr(pname, '/');
6759
6760 if (sname)
6761 *sname++ = '\0';
6762 else {
6763 sname = pname;
6764 pname = NULL;
6765 }
6766
6767 if (pname) {
6768 px = findproxy(pname, PR_CAP_BE);
6769 if (!px) {
6770 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6771 proxy_type_str(curproxy), curproxy->id,
6772 newsrv->id, pname);
6773 cfgerr++;
6774 goto next_srv;
6775 }
6776 } else
6777 px = curproxy;
6778
6779 srv = findserver(px, sname);
6780 if (!srv) {
6781 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6782 proxy_type_str(curproxy), curproxy->id,
6783 newsrv->id, sname);
6784 cfgerr++;
6785 goto next_srv;
6786 }
6787
6788 if (!(srv->state & SRV_CHECKED)) {
6789 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6790 "tracking as it does not have checks enabled.\n",
6791 proxy_type_str(curproxy), curproxy->id,
6792 newsrv->id, px->id, srv->id);
6793 cfgerr++;
6794 goto next_srv;
6795 }
6796
6797 if (curproxy != px &&
6798 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6799 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6800 "tracking: disable-on-404 option inconsistency.\n",
6801 proxy_type_str(curproxy), curproxy->id,
6802 newsrv->id, px->id, srv->id);
6803 cfgerr++;
6804 goto next_srv;
6805 }
6806
6807 /* if the other server is forced disabled, we have to do the same here */
6808 if (srv->state & SRV_MAINTAIN) {
6809 newsrv->state |= SRV_MAINTAIN;
6810 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006811 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006812 }
6813
6814 newsrv->track = srv;
6815 newsrv->tracknext = srv->tracknext;
6816 srv->tracknext = newsrv;
6817
6818 free(newsrv->trackit);
6819 newsrv->trackit = NULL;
6820 }
6821 next_srv:
6822 newsrv = newsrv->next;
6823 }
6824
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006825 /* We have to initialize the server lookup mechanism depending
6826 * on what LB algorithm was choosen.
6827 */
6828
6829 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6830 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6831 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006832 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6833 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6834 init_server_map(curproxy);
6835 } else {
6836 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6837 fwrr_init_server_groups(curproxy);
6838 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006839 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006840
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006841 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006842 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6843 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6844 fwlc_init_server_tree(curproxy);
6845 } else {
6846 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6847 fas_init_server_tree(curproxy);
6848 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006849 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006850
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006851 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006852 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6853 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6854 chash_init_server_tree(curproxy);
6855 } else {
6856 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6857 init_server_map(curproxy);
6858 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006859 break;
6860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006861
6862 if (curproxy->options & PR_O_LOGASAP)
6863 curproxy->to_log &= ~LW_BYTES;
6864
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006865 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006866 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006867 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6868 proxy_type_str(curproxy), curproxy->id);
6869 err_code |= ERR_WARN;
6870 }
6871
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006872 if (curproxy->mode != PR_MODE_HTTP) {
6873 int optnum;
6874
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006875 if (curproxy->uri_auth) {
6876 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6877 proxy_type_str(curproxy), curproxy->id);
6878 err_code |= ERR_WARN;
6879 curproxy->uri_auth = NULL;
6880 }
6881
Willy Tarreau87cf5142011-08-19 22:57:24 +02006882 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006883 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6884 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6885 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006886 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006887 }
6888
6889 if (curproxy->options & PR_O_ORGTO) {
6890 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6891 "originalto", proxy_type_str(curproxy), curproxy->id);
6892 err_code |= ERR_WARN;
6893 curproxy->options &= ~PR_O_ORGTO;
6894 }
6895
6896 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6897 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6898 (curproxy->cap & cfg_opts[optnum].cap) &&
6899 (curproxy->options & cfg_opts[optnum].val)) {
6900 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6901 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6902 err_code |= ERR_WARN;
6903 curproxy->options &= ~cfg_opts[optnum].val;
6904 }
6905 }
6906
6907 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6908 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6909 (curproxy->cap & cfg_opts2[optnum].cap) &&
6910 (curproxy->options2 & cfg_opts2[optnum].val)) {
6911 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6912 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6913 err_code |= ERR_WARN;
6914 curproxy->options2 &= ~cfg_opts2[optnum].val;
6915 }
6916 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006917
Pieter Baauwd551fb52013-05-08 22:49:23 +02006918#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006919 if (curproxy->conn_src.bind_hdr_occ) {
6920 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006921 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006922 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006923 err_code |= ERR_WARN;
6924 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006925#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006926 }
6927
Willy Tarreaubaaee002006-06-26 02:48:02 +02006928 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006929 * ensure that we're not cross-dressing a TCP server into HTTP.
6930 */
6931 newsrv = curproxy->srv;
6932 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006933 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006934 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6935 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006936 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006937 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006938
Willy Tarreau0cec3312011-10-31 13:49:26 +01006939 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6940 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6941 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6942 err_code |= ERR_WARN;
6943 }
6944
Willy Tarreau82ffa392013-08-13 17:19:08 +02006945 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6946 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6947 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6948 err_code |= ERR_WARN;
6949 }
6950
Pieter Baauwd551fb52013-05-08 22:49:23 +02006951#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006952 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6953 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006954 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 +01006955 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006956 err_code |= ERR_WARN;
6957 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006958#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006959 newsrv = newsrv->next;
6960 }
6961
Willy Tarreauc1a21672009-08-16 22:37:44 +02006962 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006963 if (!curproxy->accept)
6964 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006965
Willy Tarreauc1a21672009-08-16 22:37:44 +02006966 if (curproxy->tcp_req.inspect_delay ||
6967 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006968 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006969
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006970 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006971 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006972 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006973 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006974
6975 /* both TCP and HTTP must check switching rules */
6976 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6977 }
6978
6979 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006980 if (curproxy->tcp_req.inspect_delay ||
6981 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6982 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6983
Emeric Brun97679e72010-09-23 17:56:44 +02006984 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6985 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6986
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006987 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006988 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006989 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006990 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006991
6992 /* If the backend does requires RDP cookie persistence, we have to
6993 * enable the corresponding analyser.
6994 */
6995 if (curproxy->options2 & PR_O2_RDPC_PRST)
6996 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6997 }
6998
Emeric Brunc52962f2012-11-15 18:28:02 +01006999#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007000 /* Configure SSL for each bind line.
7001 * Note: if configuration fails at some point, the ->ctx member
7002 * remains NULL so that listeners can later detach.
7003 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007004 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007005 if (!bind_conf->is_ssl) {
7006 if (bind_conf->default_ctx) {
7007 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7008 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7009 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007010 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007011 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007012 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007013 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007014 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007015 cfgerr++;
7016 continue;
7017 }
7018
Emeric Brun4b3091e2012-09-24 15:48:52 +02007019 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007020 Alert("Unable to allocate SSL session cache.\n");
7021 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007022 continue;
7023 }
7024
Emeric Brunfc0421f2012-09-07 17:30:07 +02007025 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007026 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007027 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007028#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007029
Willy Tarreaue6b98942007-10-29 01:09:36 +01007030 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007031 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007032 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007033 if (!listener->luid) {
7034 /* listener ID not set, use automatic numbering with first
7035 * spare entry starting with next_luid.
7036 */
7037 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7038 listener->conf.id.key = listener->luid = next_id;
7039 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007040 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007041 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007042
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007043 /* enable separate counters */
7044 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7045 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007046 if (!listener->name)
7047 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007048 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007049
Willy Tarreaue6b98942007-10-29 01:09:36 +01007050 if (curproxy->options & PR_O_TCP_NOLING)
7051 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007052 if (!listener->maxconn)
7053 listener->maxconn = curproxy->maxconn;
7054 if (!listener->backlog)
7055 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007056 if (!listener->maxaccept)
7057 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7058
7059 /* we want to have an optimal behaviour on single process mode to
7060 * maximize the work at once, but in multi-process we want to keep
7061 * some fairness between processes, so we target half of the max
7062 * number of events to be balanced over all the processes the proxy
7063 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7064 * used to disable the limit.
7065 */
7066 if (listener->maxaccept > 0) {
7067 if (nbproc > 1)
7068 listener->maxaccept = (listener->maxaccept + 1) / 2;
7069 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7070 }
7071
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007072 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007073 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007074 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007075 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007076
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007077 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7078 listener->options |= LI_O_TCP_RULES;
7079
Willy Tarreaude3041d2010-05-31 10:56:17 +02007080 if (curproxy->mon_mask.s_addr)
7081 listener->options |= LI_O_CHK_MONNET;
7082
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007083 /* smart accept mode is automatic in HTTP mode */
7084 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007085 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007086 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7087 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007088 }
7089
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007090 /* Release unused SSL configs */
7091 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7092 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007093 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007094#ifdef USE_OPENSSL
7095 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007096 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007097 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007098 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007099 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007100#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007101 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007102
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007103 /* Check multi-process mode compatibility for the current proxy */
7104 if (global.nbproc > 1) {
7105 int nbproc = 0;
7106 if (curproxy->bind_proc) {
7107 int proc;
7108 for (proc = 0; proc < global.nbproc; proc++) {
7109 if (curproxy->bind_proc & (1 << proc)) {
7110 nbproc++;
7111 }
7112 }
7113 } else {
7114 nbproc = global.nbproc;
7115 }
7116 if (curproxy->table.peers.name) {
7117 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7118 curproxy->id);
7119 cfgerr++;
7120 }
7121 if (nbproc > 1) {
7122 if (curproxy->uri_auth) {
7123 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7124 curproxy->id);
7125 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7126 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7127 curproxy->id);
7128 }
7129 }
7130 if (curproxy->appsession_name) {
7131 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7132 curproxy->id);
7133 }
7134 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7135 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7136 curproxy->id);
7137 }
7138 }
7139 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007140
7141 /* create the task associated with the proxy */
7142 curproxy->task = task_new();
7143 if (curproxy->task) {
7144 curproxy->task->context = curproxy;
7145 curproxy->task->process = manage_proxy;
7146 /* no need to queue, it will be done automatically if some
7147 * listener gets limited.
7148 */
7149 curproxy->task->expire = TICK_ETERNITY;
7150 } else {
7151 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7152 curproxy->id);
7153 cfgerr++;
7154 }
7155
Willy Tarreaubaaee002006-06-26 02:48:02 +02007156 curproxy = curproxy->next;
7157 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007158
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007159 /* Check multi-process mode compatibility */
7160 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007161 if (global.stats_fe && !global.stats_fe->bind_proc) {
7162 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 +01007163 }
7164 }
7165
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007166 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7167 struct auth_users *curuser;
7168 int g;
7169
7170 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7171 unsigned int group_mask = 0;
7172 char *group = NULL;
7173
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007174 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007175 continue;
7176
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007177 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007178
7179 for (g = 0; g < curuserlist->grpcnt; g++)
7180 if (!strcmp(curuserlist->groups[g], group))
7181 break;
7182
7183 if (g == curuserlist->grpcnt) {
7184 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7185 curuserlist->name, group, curuser->user);
7186 err_code |= ERR_ALERT | ERR_FATAL;
7187 goto out;
7188 }
7189
7190 group_mask |= (1 << g);
7191 }
7192
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007193 free(curuser->u.groups);
7194 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007195 }
7196
7197 for (g = 0; g < curuserlist->grpcnt; g++) {
7198 char *user = NULL;
7199
7200 if (!curuserlist->groupusers[g])
7201 continue;
7202
7203 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7204 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7205 if (!strcmp(curuser->user, user))
7206 break;
7207
7208 if (!curuser) {
7209 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7210 curuserlist->name, user, curuserlist->groups[g]);
7211 err_code |= ERR_ALERT | ERR_FATAL;
7212 goto out;
7213 }
7214
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007215 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007216 }
7217
7218 free(curuserlist->groupusers[g]);
7219 }
7220
7221 free(curuserlist->groupusers);
7222
7223#ifdef DEBUG_AUTH
7224 for (g = 0; g < curuserlist->grpcnt; g++) {
7225 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7226
7227 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007228 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007229 fprintf(stderr, " %s", curuser->user);
7230 }
7231
7232 fprintf(stderr, "\n");
7233 }
7234#endif
7235
Willy Tarreaufbb78422011-06-05 15:38:35 +02007236 }
7237
7238 /* automatically compute fullconn if not set. We must not do it in the
7239 * loop above because cross-references are not yet fully resolved.
7240 */
7241 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7242 /* If <fullconn> is not set, let's set it to 10% of the sum of
7243 * the possible incoming frontend's maxconns.
7244 */
7245 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7246 struct proxy *fe;
7247 int total = 0;
7248
7249 /* sum up the number of maxconns of frontends which
7250 * reference this backend at least once or which are
7251 * the same one ('listen').
7252 */
7253 for (fe = proxy; fe; fe = fe->next) {
7254 struct switching_rule *rule;
7255 struct hdr_exp *exp;
7256 int found = 0;
7257
7258 if (!(fe->cap & PR_CAP_FE))
7259 continue;
7260
7261 if (fe == curproxy) /* we're on a "listen" instance */
7262 found = 1;
7263
7264 if (fe->defbe.be == curproxy) /* "default_backend" */
7265 found = 1;
7266
7267 /* check if a "use_backend" rule matches */
7268 if (!found) {
7269 list_for_each_entry(rule, &fe->switching_rules, list) {
7270 if (rule->be.backend == curproxy) {
7271 found = 1;
7272 break;
7273 }
7274 }
7275 }
7276
7277 /* check if a "reqsetbe" rule matches */
7278 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7279 if (exp->action == ACT_SETBE &&
7280 (struct proxy *)exp->replace == curproxy) {
7281 found = 1;
7282 break;
7283 }
7284 }
7285
7286 /* now we've checked all possible ways to reference a backend
7287 * from a frontend.
7288 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007289 if (!found)
7290 continue;
7291 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007292 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007293 /* we have the sum of the maxconns in <total>. We only
7294 * keep 10% of that sum to set the default fullconn, with
7295 * a hard minimum of 1 (to avoid a divide by zero).
7296 */
7297 curproxy->fullconn = (total + 9) / 10;
7298 if (!curproxy->fullconn)
7299 curproxy->fullconn = 1;
7300 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007301 }
7302
Willy Tarreau056f5682010-06-06 15:51:11 +02007303 /* initialize stick-tables on backend capable proxies. This must not
7304 * be done earlier because the data size may be discovered while parsing
7305 * other proxies.
7306 */
7307 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007308 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007309
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007310 /*
7311 * Recount currently required checks.
7312 */
7313
7314 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7315 int optnum;
7316
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007317 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7318 if (curproxy->options & cfg_opts[optnum].val)
7319 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007320
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007321 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7322 if (curproxy->options2 & cfg_opts2[optnum].val)
7323 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007324 }
7325
Willy Tarreau122541c2011-09-07 21:24:49 +02007326 if (peers) {
7327 struct peers *curpeers = peers, **last;
7328 struct peer *p, *pb;
7329
7330 /* Remove all peers sections which don't have a valid listener.
7331 * This can happen when a peers section is never referenced and
7332 * does not contain a local peer.
7333 */
7334 last = &peers;
7335 while (*last) {
7336 curpeers = *last;
7337 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007338 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007339 last = &curpeers->next;
7340 continue;
7341 }
7342
7343 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7344 curpeers->id, localpeer);
7345
7346 p = curpeers->remote;
7347 while (p) {
7348 pb = p->next;
7349 free(p->id);
7350 free(p);
7351 p = pb;
7352 }
7353
7354 /* Destroy and unlink this curpeers section.
7355 * Note: curpeers is backed up into *last.
7356 */
7357 free(curpeers->id);
7358 curpeers = curpeers->next;
7359 free(*last);
7360 *last = curpeers;
7361 }
7362 }
7363
Willy Tarreau34eb6712011-10-24 18:15:04 +02007364 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007365 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007366 MEM_F_SHARED);
7367
Willy Tarreaubb925012009-07-23 13:36:36 +02007368 if (cfgerr > 0)
7369 err_code |= ERR_ALERT | ERR_FATAL;
7370 out:
7371 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007372}
7373
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007374/*
7375 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7376 * parsing sessions.
7377 */
7378void cfg_register_keywords(struct cfg_kw_list *kwl)
7379{
7380 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7381}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007382
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007383/*
7384 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7385 */
7386void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7387{
7388 LIST_DEL(&kwl->list);
7389 LIST_INIT(&kwl->list);
7390}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007391
7392/*
7393 * Local variables:
7394 * c-indent-level: 8
7395 * c-basic-offset: 8
7396 * End:
7397 */