blob: 6b27c24d84b067fb47a635bddd3fdd3e10f06430 [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 Tarreauf1e98b82010-01-28 17:59:39 +0100417/* Report it if a request ACL condition uses some response-only parameters. It
418 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
419 * Note that <cond> may be NULL and then will be ignored.
420 */
421static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
422{
423 struct acl *acl;
424
425 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
426 return 0;
427
428 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
429 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
430 file, line, acl ? acl->name : "(unknown)");
431 return ERR_WARN;
432}
433
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100434/* Report it if a request ACL condition uses some request-only volatile parameters.
435 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
436 * Note that <cond> may be NULL and then will be ignored.
437 */
438static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
439{
440 struct acl *acl;
441
442 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
443 return 0;
444
445 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
446 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
447 file, line, acl ? acl->name : "(unknown)");
448 return ERR_WARN;
449}
450
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
1325 defproxy.defsrv.inter = DEF_CHKINTR;
1326 defproxy.defsrv.fastinter = 0;
1327 defproxy.defsrv.downinter = 0;
1328 defproxy.defsrv.rise = DEF_RISETIME;
1329 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001330 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001331 defproxy.defsrv.maxqueue = 0;
1332 defproxy.defsrv.minconn = 0;
1333 defproxy.defsrv.maxconn = 0;
1334 defproxy.defsrv.slowstart = 0;
1335 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1336 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1337 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338}
1339
Willy Tarreauade5ec42010-01-28 19:33:49 +01001340
1341static int create_cond_regex_rule(const char *file, int line,
1342 struct proxy *px, int dir, int action, int flags,
1343 const char *cmd, const char *reg, const char *repl,
1344 const char **cond_start)
1345{
1346 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348 const char *err;
1349 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001350 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001351
1352 if (px == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto err;
1356 }
1357
1358 if (*reg == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1365 err_code |= ERR_WARN;
1366
Willy Tarreau5321c422010-01-28 20:35:13 +01001367 if (cond_start &&
1368 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001369 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1370 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1371 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375 }
1376 else if (cond_start && **cond_start) {
1377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1378 file, line, cmd, *cond_start);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001383 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001384 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001385 else
1386 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001387
Willy Tarreauade5ec42010-01-28 19:33:49 +01001388 preg = calloc(1, sizeof(regex_t));
1389 if (!preg) {
1390 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1391 err_code = ERR_ALERT | ERR_FATAL;
1392 goto err;
1393 }
1394
1395 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1396 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1397 err_code = ERR_ALERT | ERR_FATAL;
1398 goto err;
1399 }
1400
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001401 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001402 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001403 if (repl && err) {
1404 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1405 file, line, cmd, *err);
1406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto err;
1408 }
1409
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001410 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001411 err_code |= ERR_WARN;
1412
Willy Tarreauf4068b62012-05-08 17:37:49 +02001413 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001414 return err_code;
1415 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001416 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001417 free(preg);
1418 return err_code;
1419}
1420
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001422 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001423 * Returns the error code, 0 if OK, or any combination of :
1424 * - ERR_ABORT: must abort ASAP
1425 * - ERR_FATAL: we can continue parsing but not start the service
1426 * - ERR_WARN: a warning has been emitted
1427 * - ERR_ALERT: an alert has been emitted
1428 * Only the two first ones can stop processing, the two others are just
1429 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001431int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1432{
1433 static struct peers *curpeers = NULL;
1434 struct peer *newpeer = NULL;
1435 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001436 struct bind_conf *bind_conf;
1437 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001438 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001439 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001440
1441 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001442 if (!*args[1]) {
1443 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1444 err_code |= ERR_ALERT | ERR_FATAL;
1445 goto out;
1446 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001447
1448 err = invalid_char(args[1]);
1449 if (err) {
1450 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1451 file, linenum, *err, args[0], args[1]);
1452 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001453 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001454 }
1455
1456 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1457 /*
1458 * If there are two proxies with the same name only following
1459 * combinations are allowed:
1460 */
1461 if (strcmp(curpeers->id, args[1]) == 0) {
1462 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1463 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1464 err_code |= ERR_WARN;
1465 }
1466 }
1467
1468 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1469 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1470 err_code |= ERR_ALERT | ERR_ABORT;
1471 goto out;
1472 }
1473
1474 curpeers->next = peers;
1475 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001476 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001477 curpeers->conf.line = linenum;
1478 curpeers->last_change = now.tv_sec;
1479 curpeers->id = strdup(args[1]);
1480 }
1481 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001482 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001483 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001484 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001485
1486 if (!*args[2]) {
1487 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1488 file, linenum, args[0]);
1489 err_code |= ERR_ALERT | ERR_FATAL;
1490 goto out;
1491 }
1492
1493 err = invalid_char(args[1]);
1494 if (err) {
1495 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1496 file, linenum, *err, args[1]);
1497 err_code |= ERR_ALERT | ERR_FATAL;
1498 goto out;
1499 }
1500
1501 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1502 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1503 err_code |= ERR_ALERT | ERR_ABORT;
1504 goto out;
1505 }
1506
1507 /* the peers are linked backwards first */
1508 curpeers->count++;
1509 newpeer->next = curpeers->remote;
1510 curpeers->remote = newpeer;
1511 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001512 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001513 newpeer->conf.line = linenum;
1514
1515 newpeer->last_change = now.tv_sec;
1516 newpeer->id = strdup(args[1]);
1517
Willy Tarreau902636f2013-03-10 19:44:48 +01001518 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001519 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001520 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001523 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001524
1525 proto = protocol_by_family(sk->ss_family);
1526 if (!proto || !proto->connect) {
1527 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1528 file, linenum, args[0], args[1]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001532
1533 if (port1 != port2) {
1534 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1535 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539
Willy Tarreau2aa38802013-02-20 19:20:59 +01001540 if (!port1) {
1541 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1542 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001546
Emeric Brun32da3c42010-09-23 18:39:19 +02001547 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001548 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001549 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001550 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001551
Emeric Brun32da3c42010-09-23 18:39:19 +02001552 if (strcmp(newpeer->id, localpeer) == 0) {
1553 /* Current is local peer, it define a frontend */
1554 newpeer->local = 1;
1555
1556 if (!curpeers->peers_fe) {
1557 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1558 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1559 err_code |= ERR_ALERT | ERR_ABORT;
1560 goto out;
1561 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001562
Willy Tarreau237250c2011-07-29 01:49:03 +02001563 init_new_proxy(curpeers->peers_fe);
1564 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001565
1566 curpeers->peers_fe->last_change = now.tv_sec;
1567 curpeers->peers_fe->id = strdup(args[1]);
1568 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001569 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1571 curpeers->peers_fe->timeout.connect = 5000;
1572 curpeers->peers_fe->accept = peer_accept;
1573 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001574 curpeers->peers_fe->conf.file = strdup(file);
1575 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001576
1577 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1578
Willy Tarreau902636f2013-03-10 19:44:48 +01001579 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1580 if (errmsg && *errmsg) {
1581 indent_msg(&errmsg, 2);
1582 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001583 }
1584 else
1585 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1586 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001587 err_code |= ERR_FATAL;
1588 goto out;
1589 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001590
1591 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1592 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1593 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1594 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1595 l->accept = session_accept;
1596 l->handler = process_session;
1597 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1598 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1599 global.maxsock += l->maxconn;
1600 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001601 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001602 else {
1603 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1604 file, linenum, args[0], args[1],
1605 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1606 err_code |= ERR_FATAL;
1607 goto out;
1608 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001609 }
1610 } /* neither "peer" nor "peers" */
1611 else if (*args[0] != 0) {
1612 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1613 err_code |= ERR_ALERT | ERR_FATAL;
1614 goto out;
1615 }
1616
1617out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001618 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001619 return err_code;
1620}
1621
1622
Willy Tarreau3842f002009-06-14 11:39:52 +02001623int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624{
1625 static struct proxy *curproxy = NULL;
1626 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001627 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001628 int rc;
1629 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001630 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001631 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001632 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001633 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001634 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635
Willy Tarreau977b8e42006-12-29 14:19:17 +01001636 if (!strcmp(args[0], "listen"))
1637 rc = PR_CAP_LISTEN;
1638 else if (!strcmp(args[0], "frontend"))
1639 rc = PR_CAP_FE | PR_CAP_RS;
1640 else if (!strcmp(args[0], "backend"))
1641 rc = PR_CAP_BE | PR_CAP_RS;
1642 else if (!strcmp(args[0], "ruleset"))
1643 rc = PR_CAP_RS;
1644 else
1645 rc = PR_CAP_NONE;
1646
1647 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 if (!*args[1]) {
1649 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1650 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_ALERT | ERR_ABORT;
1653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001655
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001656 err = invalid_char(args[1]);
1657 if (err) {
1658 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1659 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001661 }
1662
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001663 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1664 /*
1665 * If there are two proxies with the same name only following
1666 * combinations are allowed:
1667 *
1668 * listen backend frontend ruleset
1669 * listen - - - -
1670 * backend - - OK -
1671 * frontend - OK - -
1672 * ruleset - - - -
1673 */
1674
1675 if (!strcmp(curproxy->id, args[1]) &&
1676 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1677 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001678 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1679 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1680 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001682 }
1683 }
1684
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1686 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_ABORT;
1688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001690
Willy Tarreau97cb7802010-01-03 20:23:58 +01001691 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 curproxy->next = proxy;
1693 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001694 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001695 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001696 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001698 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699
1700 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001701 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001702 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001703
Willy Tarreau4348fad2012-09-20 16:48:07 +02001704 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1705
Willy Tarreau902636f2013-03-10 19:44:48 +01001706 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1707 if (errmsg && *errmsg) {
1708 indent_msg(&errmsg, 2);
1709 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001710 }
1711 else
1712 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1713 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001714 err_code |= ERR_FATAL;
1715 goto out;
1716 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001717
Willy Tarreau4348fad2012-09-20 16:48:07 +02001718 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001719 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 }
1722
1723 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001724 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001725 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001726
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001729 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001730 curproxy->no_options = defproxy.no_options;
1731 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001732 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001733 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001734 curproxy->except_net = defproxy.except_net;
1735 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001736 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001737 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001739 if (defproxy.fwdfor_hdr_len) {
1740 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1741 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1742 }
1743
Willy Tarreaub86db342009-11-30 11:50:16 +01001744 if (defproxy.orgto_hdr_len) {
1745 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1746 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1747 }
1748
Mark Lamourinec2247f02012-01-04 13:02:01 -05001749 if (defproxy.server_id_hdr_len) {
1750 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1751 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1752 }
1753
Willy Tarreau977b8e42006-12-29 14:19:17 +01001754 if (curproxy->cap & PR_CAP_FE) {
1755 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001756 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001757 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001758
1759 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001760 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1761 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001762
1763 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765
Willy Tarreau977b8e42006-12-29 14:19:17 +01001766 if (curproxy->cap & PR_CAP_BE) {
1767 curproxy->fullconn = defproxy.fullconn;
1768 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001770 if (defproxy.check_req) {
1771 curproxy->check_req = calloc(1, defproxy.check_len);
1772 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1773 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001774 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001776 if (defproxy.expect_str) {
1777 curproxy->expect_str = strdup(defproxy.expect_str);
1778 if (defproxy.expect_regex) {
1779 /* note: this regex is known to be valid */
1780 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1781 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1782 }
1783 }
1784
Willy Tarreau67402132012-05-31 20:40:20 +02001785 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786 if (defproxy.cookie_name)
1787 curproxy->cookie_name = strdup(defproxy.cookie_name);
1788 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001789 if (defproxy.cookie_domain)
1790 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001791
Willy Tarreau31936852010-10-06 16:59:56 +02001792 if (defproxy.cookie_maxidle)
1793 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1794
1795 if (defproxy.cookie_maxlife)
1796 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1797
Emeric Brun647caf12009-06-30 17:57:00 +02001798 if (defproxy.rdp_cookie_name)
1799 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1800 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1801
Willy Tarreau01732802007-11-01 22:48:15 +01001802 if (defproxy.url_param_name)
1803 curproxy->url_param_name = strdup(defproxy.url_param_name);
1804 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001805
Benoitaffb4812009-03-25 13:02:10 +01001806 if (defproxy.hh_name)
1807 curproxy->hh_name = strdup(defproxy.hh_name);
1808 curproxy->hh_len = defproxy.hh_len;
1809 curproxy->hh_match_domain = defproxy.hh_match_domain;
1810
Willy Tarreauef9a3602012-12-08 22:29:20 +01001811 if (defproxy.conn_src.iface_name)
1812 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1813 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1814 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001817 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001818 if (defproxy.capture_name)
1819 curproxy->capture_name = strdup(defproxy.capture_name);
1820 curproxy->capture_namelen = defproxy.capture_namelen;
1821 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823
Willy Tarreau977b8e42006-12-29 14:19:17 +01001824 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001825 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001826 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001827 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001828 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001829 curproxy->uri_auth = defproxy.uri_auth;
1830 curproxy->mon_net = defproxy.mon_net;
1831 curproxy->mon_mask = defproxy.mon_mask;
1832 if (defproxy.monitor_uri)
1833 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1834 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001835 if (defproxy.defbe.name)
1836 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001837
1838 /* get either a pointer to the logformat string or a copy of it */
1839 curproxy->logformat_string = defproxy.logformat_string;
1840 if (curproxy->logformat_string &&
1841 curproxy->logformat_string != default_http_log_format &&
1842 curproxy->logformat_string != default_tcp_log_format &&
1843 curproxy->logformat_string != clf_http_log_format)
1844 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001845 }
1846
1847 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001848 curproxy->timeout.connect = defproxy.timeout.connect;
1849 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001850 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001851 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001852 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001853 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001854 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001855 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001856 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857 }
1858
Willy Tarreaubaaee002006-06-26 02:48:02 +02001859 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001860
1861 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001862 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001863 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001864 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001865 LIST_INIT(&node->list);
1866 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1867 }
1868
Willy Tarreau196729e2012-05-31 19:30:26 +02001869 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1870 if (curproxy->uniqueid_format_string)
1871 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001872
1873 /* copy default header unique id */
1874 if (defproxy.header_unique_id)
1875 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1876
William Lallemand82fe75c2012-10-23 10:25:10 +02001877 /* default compression options */
1878 if (defproxy.comp != NULL) {
1879 curproxy->comp = calloc(1, sizeof(struct comp));
1880 curproxy->comp->algos = defproxy.comp->algos;
1881 curproxy->comp->types = defproxy.comp->types;
1882 }
1883
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001885 curproxy->conf.used_listener_id = EB_ROOT;
1886 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001887
Willy Tarreau93893792009-07-23 13:19:11 +02001888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
1890 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1891 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001892 /* FIXME-20070101: we should do this too at the end of the
1893 * config parsing to free all default values.
1894 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001895 free(defproxy.check_req);
1896 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001897 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001898 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001899 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001900 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001901 free(defproxy.capture_name);
1902 free(defproxy.monitor_uri);
1903 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001904 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001905 free(defproxy.fwdfor_hdr_name);
1906 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001907 free(defproxy.orgto_hdr_name);
1908 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001909 free(defproxy.server_id_hdr_name);
1910 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001911 free(defproxy.expect_str);
1912 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001913
Willy Tarreau39b06652012-06-01 10:58:06 +02001914 if (defproxy.logformat_string != default_http_log_format &&
1915 defproxy.logformat_string != default_tcp_log_format &&
1916 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001917 free(defproxy.logformat_string);
1918
1919 free(defproxy.uniqueid_format_string);
1920
Willy Tarreaua534fea2008-08-03 12:19:50 +02001921 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001922 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 /* we cannot free uri_auth because it might already be used */
1925 init_default_instance();
1926 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001927 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 }
1930 else if (curproxy == NULL) {
1931 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 }
1935
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936
1937 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001939 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001940 int cur_arg;
1941
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 if (curproxy == &defproxy) {
1943 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001947 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949
Willy Tarreau24709282013-03-10 21:32:12 +01001950 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001951 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001956
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001957 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001958
1959 /* use default settings for unix sockets */
1960 bind_conf->ux.uid = global.unix_bind.ux.uid;
1961 bind_conf->ux.gid = global.unix_bind.ux.gid;
1962 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001963
1964 /* NOTE: the following line might create several listeners if there
1965 * are comma-separated IPs or port ranges. So all further processing
1966 * will have to be applied to all listeners created after last_listen.
1967 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001968 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1969 if (errmsg && *errmsg) {
1970 indent_msg(&errmsg, 2);
1971 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001972 }
1973 else
1974 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1975 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
1978 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001979
Willy Tarreau4348fad2012-09-20 16:48:07 +02001980 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1981 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001982 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001983 }
1984
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001985 cur_arg = 2;
1986 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001987 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001988 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001989 char *err;
1990
Willy Tarreau26982662012-09-12 23:17:10 +02001991 kw = bind_find_kw(args[cur_arg]);
1992 if (kw) {
1993 char *err = NULL;
1994 int code;
1995
1996 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001997 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1998 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001999 cur_arg += 1 + kw->skip ;
2000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
2002 }
2003
Willy Tarreau4348fad2012-09-20 16:48:07 +02002004 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002005 err_code |= code;
2006
2007 if (code) {
2008 if (err && *err) {
2009 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002010 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002011 }
2012 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002013 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2014 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002015 if (code & ERR_FATAL) {
2016 free(err);
2017 cur_arg += 1 + kw->skip;
2018 goto out;
2019 }
2020 }
2021 free(err);
2022 cur_arg += 1 + kw->skip;
2023 continue;
2024 }
2025
Willy Tarreau8638f482012-09-18 18:01:17 +02002026 err = NULL;
2027 if (!bind_dumped) {
2028 bind_dump_kws(&err);
2029 indent_msg(&err, 4);
2030 bind_dumped = 1;
2031 }
2032
2033 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2034 file, linenum, args[0], args[1], args[cur_arg],
2035 err ? " Registered keywords :" : "", err ? err : "");
2036 free(err);
2037
Willy Tarreau93893792009-07-23 13:19:11 +02002038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002040 }
Willy Tarreau93893792009-07-23 13:19:11 +02002041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 }
2043 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2044 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2045 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002050 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002052
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 /* flush useless bits */
2054 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002057 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002058 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002060
Willy Tarreau1c47f852006-07-09 08:22:27 +02002061 if (!*args[1]) {
2062 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002066 }
2067
Willy Tarreaua534fea2008-08-03 12:19:50 +02002068 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002069 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002070 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002071 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002072 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2073
Willy Tarreau93893792009-07-23 13:19:11 +02002074 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2077 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2078 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2079 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2080 else {
2081 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 }
2085 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002086 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002087 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002088
2089 if (curproxy == &defproxy) {
2090 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2091 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002094 }
2095
2096 if (!*args[1]) {
2097 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2098 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002101 }
2102
2103 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002104 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002105
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002106 if (curproxy->uuid <= 0) {
2107 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002108 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002111 }
2112
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002113 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2114 if (node) {
2115 struct proxy *target = container_of(node, struct proxy, conf.id);
2116 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2117 file, linenum, proxy_type_str(curproxy), curproxy->id,
2118 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
2121 }
2122 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002123 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002124 else if (!strcmp(args[0], "description")) {
2125 int i, len=0;
2126 char *d;
2127
Cyril Bonté99ed3272010-01-24 23:29:44 +01002128 if (curproxy == &defproxy) {
2129 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2130 file, linenum, args[0]);
2131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
2133 }
2134
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002135 if (!*args[1]) {
2136 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2137 file, linenum, args[0]);
2138 return -1;
2139 }
2140
2141 for(i=1; *args[i]; i++)
2142 len += strlen(args[i])+1;
2143
2144 d = (char *)calloc(1, len);
2145 curproxy->desc = d;
2146
2147 d += sprintf(d, "%s", args[1]);
2148 for(i=2; *args[i]; i++)
2149 d += sprintf(d, " %s", args[i]);
2150
2151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2153 curproxy->state = PR_STSTOPPED;
2154 }
2155 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2156 curproxy->state = PR_STNEW;
2157 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002158 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2159 int cur_arg = 1;
2160 unsigned int set = 0;
2161
2162 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002163 unsigned int low, high;
2164
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002165 if (strcmp(args[cur_arg], "all") == 0) {
2166 set = 0;
2167 break;
2168 }
2169 else if (strcmp(args[cur_arg], "odd") == 0) {
2170 set |= 0x55555555;
2171 }
2172 else if (strcmp(args[cur_arg], "even") == 0) {
2173 set |= 0xAAAAAAAA;
2174 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002175 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002176 char *dash = strchr(args[cur_arg], '-');
2177
2178 low = high = str2uic(args[cur_arg]);
2179 if (dash)
2180 high = str2uic(dash + 1);
2181
2182 if (high < low) {
2183 unsigned int swap = low;
2184 low = high;
2185 high = swap;
2186 }
2187
2188 if (low < 1 || high > 32) {
2189 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002190 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002193 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002194
2195 if (high > global.nbproc) {
2196 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2197 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002199 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002200 while (low <= high)
2201 set |= 1 << (low++ - 1);
2202 }
2203 else {
2204 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2205 file, linenum, args[0]);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002208 }
2209 cur_arg++;
2210 }
2211 curproxy->bind_proc = set;
2212 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002213 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002214 if (curproxy == &defproxy) {
2215 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002218 }
2219
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002220 err = invalid_char(args[1]);
2221 if (err) {
2222 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2223 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002225 }
2226
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002227 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2228 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2229 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002232 }
2233 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2235 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002239
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 if (*(args[1]) == 0) {
2241 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002246
Willy Tarreau67402132012-05-31 20:40:20 +02002247 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002248 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002249 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002250 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 curproxy->cookie_name = strdup(args[1]);
2252 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002253
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 cur_arg = 2;
2255 while (*(args[cur_arg])) {
2256 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002257 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 }
2259 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002260 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
2262 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002263 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 }
2265 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002266 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 }
2268 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002269 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002271 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002272 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002275 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002277 else if (!strcmp(args[cur_arg], "httponly")) {
2278 curproxy->ck_opts |= PR_CK_HTTPONLY;
2279 }
2280 else if (!strcmp(args[cur_arg], "secure")) {
2281 curproxy->ck_opts |= PR_CK_SECURE;
2282 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002283 else if (!strcmp(args[cur_arg], "domain")) {
2284 if (!*args[cur_arg + 1]) {
2285 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2286 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002289 }
2290
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002291 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002292 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002293 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2294 " dots nor does not start with a dot."
2295 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002296 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002297 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002298 }
2299
2300 err = invalid_domainchar(args[cur_arg + 1]);
2301 if (err) {
2302 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2303 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002306 }
2307
Willy Tarreau68a897b2009-12-03 23:28:34 +01002308 if (!curproxy->cookie_domain) {
2309 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2310 } else {
2311 /* one domain was already specified, add another one by
2312 * building the string which will be returned along with
2313 * the cookie.
2314 */
2315 char *new_ptr;
2316 int new_len = strlen(curproxy->cookie_domain) +
2317 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2318 new_ptr = malloc(new_len);
2319 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2320 free(curproxy->cookie_domain);
2321 curproxy->cookie_domain = new_ptr;
2322 }
Willy Tarreau31936852010-10-06 16:59:56 +02002323 cur_arg++;
2324 }
2325 else if (!strcmp(args[cur_arg], "maxidle")) {
2326 unsigned int maxidle;
2327 const char *res;
2328
2329 if (!*args[cur_arg + 1]) {
2330 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2331 file, linenum, args[cur_arg]);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335
2336 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2337 if (res) {
2338 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2339 file, linenum, *res, args[cur_arg]);
2340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
2343 curproxy->cookie_maxidle = maxidle;
2344 cur_arg++;
2345 }
2346 else if (!strcmp(args[cur_arg], "maxlife")) {
2347 unsigned int maxlife;
2348 const char *res;
2349
2350 if (!*args[cur_arg + 1]) {
2351 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2352 file, linenum, args[cur_arg]);
2353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
2355 }
2356
2357 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2358 if (res) {
2359 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2360 file, linenum, *res, args[cur_arg]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002365 cur_arg++;
2366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002368 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 +02002369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373 cur_arg++;
2374 }
Willy Tarreau67402132012-05-31 20:40:20 +02002375 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2377 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 }
2380
Willy Tarreau67402132012-05-31 20:40:20 +02002381 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2383 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002386
Willy Tarreau67402132012-05-31 20:40:20 +02002387 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002388 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2389 file, linenum);
2390 err_code |= ERR_ALERT | ERR_FATAL;
2391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002393 else if (!strcmp(args[0], "persist")) { /* persist */
2394 if (*(args[1]) == 0) {
2395 Alert("parsing [%s:%d] : missing persist method.\n",
2396 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002399 }
2400
2401 if (!strncmp(args[1], "rdp-cookie", 10)) {
2402 curproxy->options2 |= PR_O2_RDPC_PRST;
2403
Emeric Brunb982a3d2010-01-04 15:45:53 +01002404 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002405 const char *beg, *end;
2406
2407 beg = args[1] + 11;
2408 end = strchr(beg, ')');
2409
2410 if (!end || end == beg) {
2411 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2412 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002415 }
2416
2417 free(curproxy->rdp_cookie_name);
2418 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2419 curproxy->rdp_cookie_len = end-beg;
2420 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002421 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002422 free(curproxy->rdp_cookie_name);
2423 curproxy->rdp_cookie_name = strdup("msts");
2424 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2425 }
2426 else { /* syntax */
2427 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2428 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002431 }
2432 }
2433 else {
2434 Alert("parsing [%s:%d] : unknown persist method.\n",
2435 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002438 }
2439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002441 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002443 if (curproxy == &defproxy) {
2444 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
2447 }
2448
Willy Tarreau977b8e42006-12-29 14:19:17 +01002449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002453 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
2458 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002459 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 curproxy->appsession_name = strdup(args[1]);
2461 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2462 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002463 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2464 if (err) {
2465 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2466 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002469 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002470 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002471
Willy Tarreau51041c72007-09-09 21:56:53 +02002472 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2473 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_ABORT;
2475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002477
2478 cur_arg = 6;
2479 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002480 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2481 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002482 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002483 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002484 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002485 } else if (!strcmp(args[cur_arg], "prefix")) {
2486 curproxy->options2 |= PR_O2_AS_PFX;
2487 } else if (!strcmp(args[cur_arg], "mode")) {
2488 if (!*args[cur_arg + 1]) {
2489 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2490 file, linenum, args[0], args[cur_arg]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494
2495 cur_arg++;
2496 if (!strcmp(args[cur_arg], "query-string")) {
2497 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2498 curproxy->options2 |= PR_O2_AS_M_QS;
2499 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2500 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2501 curproxy->options2 |= PR_O2_AS_M_PP;
2502 } else {
2503 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002508 cur_arg++;
2509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 } /* Url App Session */
2511 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002512 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002513 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002514
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002516 if (curproxy == &defproxy) {
2517 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 if (*(args[4]) == 0) {
2523 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2524 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002528 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 curproxy->capture_name = strdup(args[2]);
2530 curproxy->capture_namelen = strlen(curproxy->capture_name);
2531 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 curproxy->to_log |= LW_COOKIE;
2533 }
2534 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2535 struct cap_hdr *hdr;
2536
2537 if (curproxy == &defproxy) {
2538 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 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 }
2542
2543 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2544 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2545 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
2549
2550 hdr = calloc(sizeof(struct cap_hdr), 1);
2551 hdr->next = curproxy->req_cap;
2552 hdr->name = strdup(args[3]);
2553 hdr->namelen = strlen(args[3]);
2554 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002555 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 hdr->index = curproxy->nb_req_cap++;
2557 curproxy->req_cap = hdr;
2558 curproxy->to_log |= LW_REQHDR;
2559 }
2560 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2561 struct cap_hdr *hdr;
2562
2563 if (curproxy == &defproxy) {
2564 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 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
2568
2569 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2570 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2571 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 hdr = calloc(sizeof(struct cap_hdr), 1);
2576 hdr->next = curproxy->rsp_cap;
2577 hdr->name = strdup(args[3]);
2578 hdr->namelen = strlen(args[3]);
2579 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002580 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 hdr->index = curproxy->nb_rsp_cap++;
2582 curproxy->rsp_cap = hdr;
2583 curproxy->to_log |= LW_RSPHDR;
2584 }
2585 else {
2586 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2587 file, linenum, args[0]);
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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002593 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002595
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 if (*(args[1]) == 0) {
2597 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 }
2602 curproxy->conn_retries = atol(args[1]);
2603 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002604 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002605 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002606
2607 if (curproxy == &defproxy) {
2608 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
2611 }
2612
Willy Tarreau20b0de52012-12-24 15:45:22 +01002613 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2614 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2615 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2616 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2617 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2618 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 +01002619 file, linenum, args[0]);
2620 err_code |= ERR_WARN;
2621 }
2622
Willy Tarreauff011f22011-01-06 17:51:27 +01002623 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002624
Willy Tarreauff011f22011-01-06 17:51:27 +01002625 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002626 err_code |= ERR_ALERT | ERR_ABORT;
2627 goto out;
2628 }
2629
Willy Tarreauff011f22011-01-06 17:51:27 +01002630 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2631 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002632 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002633 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2634 /* set the header name and length into the proxy structure */
2635 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2636 err_code |= ERR_WARN;
2637
2638 if (!*args[1]) {
2639 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2640 file, linenum, args[0]);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644
2645 /* set the desired header name */
2646 free(curproxy->server_id_hdr_name);
2647 curproxy->server_id_hdr_name = strdup(args[1]);
2648 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2649 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002650 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002651 if (curproxy == &defproxy) {
2652 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002655 }
2656
Willy Tarreauef6494c2010-01-28 17:12:36 +01002657 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002658 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002662 }
2663
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002664 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2665 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2666 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002669 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002670
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002671 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002672 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002673 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002674 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002675 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002676
Cyril Bonté99ed3272010-01-24 23:29:44 +01002677 if (curproxy == &defproxy) {
2678 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
2681 }
2682
Willy Tarreau4baae242012-12-27 12:00:31 +01002683 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2684 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2685 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002688 }
2689
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002690 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002691 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreau2f476512013-03-25 19:16:31 +01002692 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002693 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002694 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002695 struct switching_rule *rule;
2696
Willy Tarreaub099aca2008-10-12 17:26:37 +02002697 if (curproxy == &defproxy) {
2698 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002701 }
2702
Willy Tarreau55ea7572007-06-17 19:56:27 +02002703 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002704 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002705
2706 if (*(args[1]) == 0) {
2707 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002710 }
2711
Willy Tarreauef6494c2010-01-28 17:12:36 +01002712 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002713 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002717 }
2718
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002719 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2720 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2721 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002724 }
2725
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002726 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002727
Willy Tarreau55ea7572007-06-17 19:56:27 +02002728 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2729 rule->cond = cond;
2730 rule->be.name = strdup(args[1]);
2731 LIST_INIT(&rule->list);
2732 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2733 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002734 else if (strcmp(args[0], "use-server") == 0) {
2735 struct server_rule *rule;
2736
2737 if (curproxy == &defproxy) {
2738 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
2741 }
2742
2743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2744 err_code |= ERR_WARN;
2745
2746 if (*(args[1]) == 0) {
2747 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
2751
2752 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2753 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2754 file, linenum, args[0]);
2755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
2758
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002759 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2760 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2761 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
2766 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2767
2768 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2769 rule->cond = cond;
2770 rule->srv.name = strdup(args[1]);
2771 LIST_INIT(&rule->list);
2772 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2773 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2774 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002775 else if ((!strcmp(args[0], "force-persist")) ||
2776 (!strcmp(args[0], "ignore-persist"))) {
2777 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002778
2779 if (curproxy == &defproxy) {
2780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784
2785 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2786 err_code |= ERR_WARN;
2787
Willy Tarreauef6494c2010-01-28 17:12:36 +01002788 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002789 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2790 file, linenum, args[0]);
2791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
2793 }
2794
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002795 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2796 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2797 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
2801
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002802 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002803
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002804 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002805 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002806 if (!strcmp(args[0], "force-persist")) {
2807 rule->type = PERSIST_TYPE_FORCE;
2808 } else {
2809 rule->type = PERSIST_TYPE_IGNORE;
2810 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002811 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002812 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002813 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002814 else if (!strcmp(args[0], "stick-table")) {
2815 int myidx = 1;
2816
Emeric Brun32da3c42010-09-23 18:39:19 +02002817 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002818 curproxy->table.type = (unsigned int)-1;
2819 while (*args[myidx]) {
2820 const char *err;
2821
2822 if (strcmp(args[myidx], "size") == 0) {
2823 myidx++;
2824 if (!*(args[myidx])) {
2825 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2826 file, linenum, args[myidx-1]);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
2830 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2831 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2832 file, linenum, *err, args[myidx-1]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002836 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002837 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002838 else if (strcmp(args[myidx], "peers") == 0) {
2839 myidx++;
2840 if (!*(args[myidx])) {
2841 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2842 file, linenum, args[myidx-1]);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845 }
2846 curproxy->table.peers.name = strdup(args[myidx++]);
2847 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002848 else if (strcmp(args[myidx], "expire") == 0) {
2849 myidx++;
2850 if (!*(args[myidx])) {
2851 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2852 file, linenum, args[myidx-1]);
2853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
2855 }
2856 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2857 if (err) {
2858 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2859 file, linenum, *err, args[myidx-1]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
2863 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002864 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002865 }
2866 else if (strcmp(args[myidx], "nopurge") == 0) {
2867 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002868 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002869 }
2870 else if (strcmp(args[myidx], "type") == 0) {
2871 myidx++;
2872 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2873 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2874 file, linenum, args[myidx]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002878 /* myidx already points to next arg */
2879 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002880 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002881 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002882 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002883
2884 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002885 nw = args[myidx];
2886 while (*nw) {
2887 /* the "store" keyword supports a comma-separated list */
2888 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002889 sa = NULL; /* store arg */
2890 while (*nw && *nw != ',') {
2891 if (*nw == '(') {
2892 *nw = 0;
2893 sa = ++nw;
2894 while (*nw != ')') {
2895 if (!*nw) {
2896 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2897 file, linenum, args[0], cw);
2898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900 }
2901 nw++;
2902 }
2903 *nw = '\0';
2904 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002905 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002906 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002907 if (*nw)
2908 *nw++ = '\0';
2909 type = stktable_get_data_type(cw);
2910 if (type < 0) {
2911 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2912 file, linenum, args[0], cw);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
Willy Tarreauac782882010-06-20 10:41:54 +02002916
2917 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2918 switch (err) {
2919 case PE_NONE: break;
2920 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002921 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2922 file, linenum, args[0], cw);
2923 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002924 break;
2925
2926 case PE_ARG_MISSING:
2927 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2928 file, linenum, args[0], cw);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931
2932 case PE_ARG_NOT_USED:
2933 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2934 file, linenum, args[0], cw);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937
2938 default:
2939 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2940 file, linenum, args[0], cw);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002943 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002944 }
2945 myidx++;
2946 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002947 else {
2948 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2949 file, linenum, args[myidx]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002952 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 }
2954
2955 if (!curproxy->table.size) {
2956 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2957 file, linenum);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
2961
2962 if (curproxy->table.type == (unsigned int)-1) {
2963 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2964 file, linenum);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
2967 }
2968 }
2969 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002970 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002971 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 int myidx = 0;
2973 const char *name = NULL;
2974 int flags;
2975
2976 if (curproxy == &defproxy) {
2977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981
2982 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2983 err_code |= ERR_WARN;
2984 goto out;
2985 }
2986
2987 myidx++;
2988 if ((strcmp(args[myidx], "store") == 0) ||
2989 (strcmp(args[myidx], "store-request") == 0)) {
2990 myidx++;
2991 flags = STK_IS_STORE;
2992 }
2993 else if (strcmp(args[myidx], "store-response") == 0) {
2994 myidx++;
2995 flags = STK_IS_STORE | STK_ON_RSP;
2996 }
2997 else if (strcmp(args[myidx], "match") == 0) {
2998 myidx++;
2999 flags = STK_IS_MATCH;
3000 }
3001 else if (strcmp(args[myidx], "on") == 0) {
3002 myidx++;
3003 flags = STK_IS_MATCH | STK_IS_STORE;
3004 }
3005 else {
3006 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
3009 }
3010
3011 if (*(args[myidx]) == 0) {
3012 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003017 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003018 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003019 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
3024 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003025 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3026 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3027 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003029 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 goto out;
3031 }
3032 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003033 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3034 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3035 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003037 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 goto out;
3039 }
3040 }
3041
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003042 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau80aca902013-01-07 15:42:20 +01003043 if (expr->fetch->use & SMP_USE_HTTP_ANY)
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003044 curproxy->acl_requires |= ACL_USE_L7_ANY;
3045
Emeric Brunb982a3d2010-01-04 15:45:53 +01003046 if (strcmp(args[myidx], "table") == 0) {
3047 myidx++;
3048 name = args[myidx++];
3049 }
3050
Willy Tarreauef6494c2010-01-28 17:12:36 +01003051 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003052 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3053 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3054 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003055 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003056 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003057 goto out;
3058 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003060 else if (*(args[myidx])) {
3061 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3062 file, linenum, args[0], args[myidx]);
3063 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003064 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003065 goto out;
3066 }
Emeric Brun97679e72010-09-23 17:56:44 +02003067 if (flags & STK_ON_RSP)
3068 err_code |= warnif_cond_requires_req(cond, file, linenum);
3069 else
3070 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003071
Emeric Brunb982a3d2010-01-04 15:45:53 +01003072 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3073 rule->cond = cond;
3074 rule->expr = expr;
3075 rule->flags = flags;
3076 rule->table.name = name ? strdup(name) : NULL;
3077 LIST_INIT(&rule->list);
3078 if (flags & STK_ON_RSP)
3079 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3080 else
3081 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003084 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003086
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3088 curproxy->uri_auth = NULL; /* we must detach from the default config */
3089
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003090 if (!*args[1]) {
3091 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003092 } else if (!strcmp(args[1], "admin")) {
3093 struct stats_admin_rule *rule;
3094
3095 if (curproxy == &defproxy) {
3096 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3102 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3103 err_code |= ERR_ALERT | ERR_ABORT;
3104 goto out;
3105 }
3106
3107 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3108 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3109 file, linenum, args[0], args[1]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003113 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3114 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3115 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
3120 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3121
3122 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3123 rule->cond = cond;
3124 LIST_INIT(&rule->list);
3125 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 } else if (!strcmp(args[1], "uri")) {
3127 if (*(args[2]) == 0) {
3128 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3132 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
3136 } else if (!strcmp(args[1], "realm")) {
3137 if (*(args[2]) == 0) {
3138 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003146 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003147 unsigned interval;
3148
3149 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3150 if (err) {
3151 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3152 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003155 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3156 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_ABORT;
3158 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003159 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003160 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003161 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003162
3163 if (curproxy == &defproxy) {
3164 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167 }
3168
3169 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3170 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
3173 }
3174
Willy Tarreauff011f22011-01-06 17:51:27 +01003175 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3176 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003177 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3178 file, linenum, args[0]);
3179 err_code |= ERR_WARN;
3180 }
3181
Willy Tarreauff011f22011-01-06 17:51:27 +01003182 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003183
Willy Tarreauff011f22011-01-06 17:51:27 +01003184 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003185 err_code |= ERR_ALERT | ERR_ABORT;
3186 goto out;
3187 }
3188
Willy Tarreauff011f22011-01-06 17:51:27 +01003189 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3190 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003191
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 } else if (!strcmp(args[1], "auth")) {
3193 if (*(args[2]) == 0) {
3194 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202 } else if (!strcmp(args[1], "scope")) {
3203 if (*(args[2]) == 0) {
3204 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 }
3212 } else if (!strcmp(args[1], "enable")) {
3213 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3214 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_ABORT;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003218 } else if (!strcmp(args[1], "hide-version")) {
3219 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3220 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_ABORT;
3222 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003223 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003224 } else if (!strcmp(args[1], "show-legends")) {
3225 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3226 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
3229 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003230 } else if (!strcmp(args[1], "show-node")) {
3231
3232 if (*args[2]) {
3233 int i;
3234 char c;
3235
3236 for (i=0; args[2][i]; i++) {
3237 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003238 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3239 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003240 break;
3241 }
3242
3243 if (!i || args[2][i]) {
3244 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3245 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3246 file, linenum, args[0], args[1]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250 }
3251
3252 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3253 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3254 err_code |= ERR_ALERT | ERR_ABORT;
3255 goto out;
3256 }
3257 } else if (!strcmp(args[1], "show-desc")) {
3258 char *desc = NULL;
3259
3260 if (*args[2]) {
3261 int i, len=0;
3262 char *d;
3263
3264 for(i=2; *args[i]; i++)
3265 len += strlen(args[i])+1;
3266
3267 desc = d = (char *)calloc(1, len);
3268
3269 d += sprintf(d, "%s", args[2]);
3270 for(i=3; *args[i]; i++)
3271 d += sprintf(d, " %s", args[i]);
3272 }
3273
3274 if (!*args[2] && !global.desc)
3275 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3276 file, linenum, args[1]);
3277 else {
3278 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3279 free(desc);
3280 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3281 err_code |= ERR_ALERT | ERR_ABORT;
3282 goto out;
3283 }
3284 free(desc);
3285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003287stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003288 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 +01003289 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293 }
3294 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003295 int optnum;
3296
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003297 if (*(args[1]) == '\0') {
3298 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003303
3304 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3305 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003306 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3307 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3308 file, linenum, cfg_opts[optnum].name);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
3311 }
Willy Tarreau93893792009-07-23 13:19:11 +02003312 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3313 err_code |= ERR_WARN;
3314 goto out;
3315 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003316
Willy Tarreau3842f002009-06-14 11:39:52 +02003317 curproxy->no_options &= ~cfg_opts[optnum].val;
3318 curproxy->options &= ~cfg_opts[optnum].val;
3319
3320 switch (kwm) {
3321 case KWM_STD:
3322 curproxy->options |= cfg_opts[optnum].val;
3323 break;
3324 case KWM_NO:
3325 curproxy->no_options |= cfg_opts[optnum].val;
3326 break;
3327 case KWM_DEF: /* already cleared */
3328 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003329 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003330
Willy Tarreau93893792009-07-23 13:19:11 +02003331 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003332 }
3333 }
3334
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003335 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3336 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003337 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3338 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3339 file, linenum, cfg_opts2[optnum].name);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
Willy Tarreau93893792009-07-23 13:19:11 +02003343 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3344 err_code |= ERR_WARN;
3345 goto out;
3346 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003347
Willy Tarreau3842f002009-06-14 11:39:52 +02003348 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3349 curproxy->options2 &= ~cfg_opts2[optnum].val;
3350
3351 switch (kwm) {
3352 case KWM_STD:
3353 curproxy->options2 |= cfg_opts2[optnum].val;
3354 break;
3355 case KWM_NO:
3356 curproxy->no_options2 |= cfg_opts2[optnum].val;
3357 break;
3358 case KWM_DEF: /* already cleared */
3359 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003360 }
Willy Tarreau93893792009-07-23 13:19:11 +02003361 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003362 }
3363 }
3364
Willy Tarreau3842f002009-06-14 11:39:52 +02003365 if (kwm != KWM_STD) {
3366 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003367 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003370 }
3371
Emeric Brun3a058f32009-06-30 18:26:00 +02003372 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003373 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003375 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003376 if (*(args[2]) != '\0') {
3377 if (!strcmp(args[2], "clf")) {
3378 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003379 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003380 } else {
3381 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003384 }
3385 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003386 if (curproxy->logformat_string != default_http_log_format &&
3387 curproxy->logformat_string != default_tcp_log_format &&
3388 curproxy->logformat_string != clf_http_log_format)
3389 free(curproxy->logformat_string);
3390 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003391 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003392 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003394 if (curproxy->logformat_string != default_http_log_format &&
3395 curproxy->logformat_string != default_tcp_log_format &&
3396 curproxy->logformat_string != clf_http_log_format)
3397 free(curproxy->logformat_string);
3398 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003399 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 else if (!strcmp(args[1], "tcpka")) {
3401 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003402 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003404
3405 if (curproxy->cap & PR_CAP_FE)
3406 curproxy->options |= PR_O_TCP_CLI_KA;
3407 if (curproxy->cap & PR_CAP_BE)
3408 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
3410 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003411 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_WARN;
3413
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003415 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003416 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003417 curproxy->options2 &= ~PR_O2_CHK_ANY;
3418 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 if (!*args[2]) { /* no argument */
3420 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3421 curproxy->check_len = strlen(DEF_CHECK_REQ);
3422 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003423 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 curproxy->check_req = (char *)malloc(reqlen);
3425 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003426 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003428 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 if (*args[4])
3430 reqlen += strlen(args[4]);
3431 else
3432 reqlen += strlen("HTTP/1.0");
3433
3434 curproxy->check_req = (char *)malloc(reqlen);
3435 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003436 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003438 }
3439 else if (!strcmp(args[1], "ssl-hello-chk")) {
3440 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003441 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003443
Willy Tarreaua534fea2008-08-03 12:19:50 +02003444 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003445 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003446 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003447 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 }
Willy Tarreau23677902007-05-08 23:50:35 +02003449 else if (!strcmp(args[1], "smtpchk")) {
3450 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003451 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003452 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003453 curproxy->options2 &= ~PR_O2_CHK_ANY;
3454 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003455
3456 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3457 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3458 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3459 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3460 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3461 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3462 curproxy->check_req = (char *)malloc(reqlen);
3463 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3464 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3465 } else {
3466 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3467 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3468 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3469 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3470 }
3471 }
3472 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003473 else if (!strcmp(args[1], "lb-agent-chk")) {
3474 /* use dynmaic health check */
3475 free(curproxy->check_req);
3476 curproxy->check_req = NULL;
3477 curproxy->options2 &= ~PR_O2_CHK_ANY;
3478 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3479 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003480 else if (!strcmp(args[1], "pgsql-check")) {
3481 /* use PostgreSQL request to check servers' health */
3482 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3483 err_code |= ERR_WARN;
3484
3485 free(curproxy->check_req);
3486 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003487 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003488 curproxy->options2 |= PR_O2_PGSQL_CHK;
3489
3490 if (*(args[2])) {
3491 int cur_arg = 2;
3492
3493 while (*(args[cur_arg])) {
3494 if (strcmp(args[cur_arg], "user") == 0) {
3495 char * packet;
3496 uint32_t packet_len;
3497 uint32_t pv;
3498
3499 /* suboption header - needs additional argument for it */
3500 if (*(args[cur_arg+1]) == 0) {
3501 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3502 file, linenum, args[0], args[1], args[cur_arg]);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
3506
3507 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3508 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3509 pv = htonl(0x30000); /* protocol version 3.0 */
3510
3511 packet = (char*) calloc(1, packet_len);
3512
3513 memcpy(packet + 4, &pv, 4);
3514
3515 /* copy "user" */
3516 memcpy(packet + 8, "user", 4);
3517
3518 /* copy username */
3519 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3520
3521 free(curproxy->check_req);
3522 curproxy->check_req = packet;
3523 curproxy->check_len = packet_len;
3524
3525 packet_len = htonl(packet_len);
3526 memcpy(packet, &packet_len, 4);
3527 cur_arg += 2;
3528 } else {
3529 /* unknown suboption - catchall */
3530 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3531 file, linenum, args[0], args[1]);
3532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
3534 }
3535 } /* end while loop */
3536 }
3537 }
3538
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003539 else if (!strcmp(args[1], "redis-check")) {
3540 /* use REDIS PING request to check servers' health */
3541 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3542 err_code |= ERR_WARN;
3543
3544 free(curproxy->check_req);
3545 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003546 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003547 curproxy->options2 |= PR_O2_REDIS_CHK;
3548
3549 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3550 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3551 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3552 }
3553
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003554 else if (!strcmp(args[1], "mysql-check")) {
3555 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003556 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3557 err_code |= ERR_WARN;
3558
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003559 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003560 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003561 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003562 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003563
3564 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3565 * const char mysql40_client_auth_pkt[] = {
3566 * "\x0e\x00\x00" // packet length
3567 * "\x01" // packet number
3568 * "\x00\x00" // client capabilities
3569 * "\x00\x00\x01" // max packet
3570 * "haproxy\x00" // username (null terminated string)
3571 * "\x00" // filler (always 0x00)
3572 * "\x01\x00\x00" // packet length
3573 * "\x00" // packet number
3574 * "\x01" // COM_QUIT command
3575 * };
3576 */
3577
3578 if (*(args[2])) {
3579 int cur_arg = 2;
3580
3581 while (*(args[cur_arg])) {
3582 if (strcmp(args[cur_arg], "user") == 0) {
3583 char *mysqluser;
3584 int packetlen, reqlen, userlen;
3585
3586 /* suboption header - needs additional argument for it */
3587 if (*(args[cur_arg+1]) == 0) {
3588 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3589 file, linenum, args[0], args[1], args[cur_arg]);
3590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
3592 }
3593 mysqluser = args[cur_arg + 1];
3594 userlen = strlen(mysqluser);
3595 packetlen = userlen + 7;
3596 reqlen = packetlen + 9;
3597
3598 free(curproxy->check_req);
3599 curproxy->check_req = (char *)calloc(1, reqlen);
3600 curproxy->check_len = reqlen;
3601
3602 snprintf(curproxy->check_req, 4, "%c%c%c",
3603 ((unsigned char) packetlen & 0xff),
3604 ((unsigned char) (packetlen >> 8) & 0xff),
3605 ((unsigned char) (packetlen >> 16) & 0xff));
3606
3607 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003608 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003609 curproxy->check_req[8] = 1;
3610 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3611 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3612 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3613 cur_arg += 2;
3614 } else {
3615 /* unknown suboption - catchall */
3616 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3617 file, linenum, args[0], args[1]);
3618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
3620 }
3621 } /* end while loop */
3622 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003623 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003624 else if (!strcmp(args[1], "ldap-check")) {
3625 /* use LDAP request to check servers' health */
3626 free(curproxy->check_req);
3627 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003628 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003629 curproxy->options2 |= PR_O2_LDAP_CHK;
3630
3631 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3632 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3633 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3634 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003635 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003636 int cur_arg;
3637
3638 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3639 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003640 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003641
Willy Tarreau87cf5142011-08-19 22:57:24 +02003642 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003643
3644 free(curproxy->fwdfor_hdr_name);
3645 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3646 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3647
3648 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3649 cur_arg = 2;
3650 while (*(args[cur_arg])) {
3651 if (!strcmp(args[cur_arg], "except")) {
3652 /* suboption except - needs additional argument for it */
3653 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3654 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3655 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003658 }
3659 /* flush useless bits */
3660 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003661 cur_arg += 2;
3662 } else if (!strcmp(args[cur_arg], "header")) {
3663 /* suboption header - needs additional argument for it */
3664 if (*(args[cur_arg+1]) == 0) {
3665 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3666 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003667 err_code |= ERR_ALERT | ERR_FATAL;
3668 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003669 }
3670 free(curproxy->fwdfor_hdr_name);
3671 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3672 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3673 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003674 } else if (!strcmp(args[cur_arg], "if-none")) {
3675 curproxy->options &= ~PR_O_FF_ALWAYS;
3676 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003677 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003678 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003679 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003680 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003683 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003684 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003685 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003686 else if (!strcmp(args[1], "originalto")) {
3687 int cur_arg;
3688
3689 /* insert x-original-to field, but not for the IP address listed as an except.
3690 * set default options (ie: bitfield, header name, etc)
3691 */
3692
3693 curproxy->options |= PR_O_ORGTO;
3694
3695 free(curproxy->orgto_hdr_name);
3696 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3697 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3698
Willy Tarreau87cf5142011-08-19 22:57:24 +02003699 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003700 cur_arg = 2;
3701 while (*(args[cur_arg])) {
3702 if (!strcmp(args[cur_arg], "except")) {
3703 /* suboption except - needs additional argument for it */
3704 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3705 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3706 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003709 }
3710 /* flush useless bits */
3711 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3712 cur_arg += 2;
3713 } else if (!strcmp(args[cur_arg], "header")) {
3714 /* suboption header - needs additional argument for it */
3715 if (*(args[cur_arg+1]) == 0) {
3716 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3717 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003720 }
3721 free(curproxy->orgto_hdr_name);
3722 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3723 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3724 cur_arg += 2;
3725 } else {
3726 /* unknown suboption - catchall */
3727 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3728 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003731 }
3732 } /* end while loop */
3733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 else {
3735 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 }
Willy Tarreau93893792009-07-23 13:19:11 +02003739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003741 else if (!strcmp(args[0], "default_backend")) {
3742 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003744
3745 if (*(args[1]) == 0) {
3746 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003749 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003750 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003751 curproxy->defbe.name = strdup(args[1]);
3752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003753 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003754 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003756
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003757 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3758 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 /* enable reconnections to dispatch */
3761 curproxy->options |= PR_O_REDISP;
3762 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003763 else if (!strcmp(args[0], "http-check")) {
3764 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003766
3767 if (strcmp(args[1], "disable-on-404") == 0) {
3768 /* enable a graceful server shutdown on an HTTP 404 response */
3769 curproxy->options |= PR_O_DISABLE404;
3770 }
Willy Tarreauef781042010-01-27 11:53:01 +01003771 else if (strcmp(args[1], "send-state") == 0) {
3772 /* enable emission of the apparent state of a server in HTTP checks */
3773 curproxy->options2 |= PR_O2_CHK_SNDST;
3774 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003775 else if (strcmp(args[1], "expect") == 0) {
3776 const char *ptr_arg;
3777 int cur_arg;
3778
3779 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3780 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
3783 }
3784
3785 cur_arg = 2;
3786 /* consider exclamation marks, sole or at the beginning of a word */
3787 while (*(ptr_arg = args[cur_arg])) {
3788 while (*ptr_arg == '!') {
3789 curproxy->options2 ^= PR_O2_EXP_INV;
3790 ptr_arg++;
3791 }
3792 if (*ptr_arg)
3793 break;
3794 cur_arg++;
3795 }
3796 /* now ptr_arg points to the beginning of a word past any possible
3797 * exclamation mark, and cur_arg is the argument which holds this word.
3798 */
3799 if (strcmp(ptr_arg, "status") == 0) {
3800 if (!*(args[cur_arg + 1])) {
3801 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3802 file, linenum, args[0], args[1], ptr_arg);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003807 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003808 curproxy->expect_str = strdup(args[cur_arg + 1]);
3809 }
3810 else if (strcmp(ptr_arg, "string") == 0) {
3811 if (!*(args[cur_arg + 1])) {
3812 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3813 file, linenum, args[0], args[1], ptr_arg);
3814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
3816 }
3817 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003818 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003819 curproxy->expect_str = strdup(args[cur_arg + 1]);
3820 }
3821 else if (strcmp(ptr_arg, "rstatus") == 0) {
3822 if (!*(args[cur_arg + 1])) {
3823 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3824 file, linenum, args[0], args[1], ptr_arg);
3825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
3827 }
3828 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003829 free(curproxy->expect_str);
3830 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3831 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003832 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3833 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3834 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3835 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839 }
3840 else if (strcmp(ptr_arg, "rstring") == 0) {
3841 if (!*(args[cur_arg + 1])) {
3842 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3843 file, linenum, args[0], args[1], ptr_arg);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003848 free(curproxy->expect_str);
3849 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3850 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003851 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3852 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3853 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3854 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
3858 }
3859 else {
3860 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3861 file, linenum, args[0], args[1], ptr_arg);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
3865 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003866 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003867 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 +02003868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003870 }
3871 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003872 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003873 if (curproxy == &defproxy) {
3874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003877 }
3878
Willy Tarreaub80c2302007-11-30 20:51:32 +01003879 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003881
3882 if (strcmp(args[1], "fail") == 0) {
3883 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003884 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003885 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3886 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003889 }
3890
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003891 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3892 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3893 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003896 }
3897 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3898 }
3899 else {
3900 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003903 }
3904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905#ifdef TPROXY
3906 else if (!strcmp(args[0], "transparent")) {
3907 /* enable transparent proxy connections */
3908 curproxy->options |= PR_O_TRANSP;
3909 }
3910#endif
3911 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003912 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003914
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 if (*(args[1]) == 0) {
3916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 }
3920 curproxy->maxconn = atol(args[1]);
3921 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003922 else if (!strcmp(args[0], "backlog")) { /* backlog */
3923 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003925
3926 if (*(args[1]) == 0) {
3927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003930 }
3931 curproxy->backlog = atol(args[1]);
3932 }
Willy Tarreau86034312006-12-29 00:10:33 +01003933 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003936
Willy Tarreau86034312006-12-29 00:10:33 +01003937 if (*(args[1]) == 0) {
3938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003941 }
3942 curproxy->fullconn = atol(args[1]);
3943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3945 if (*(args[1]) == 0) {
3946 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003950 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3951 if (err) {
3952 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3953 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003956 }
3957 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958 }
3959 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003960 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003961 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003962 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003963
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 if (curproxy == &defproxy) {
3965 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003969 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003971
Willy Tarreau902636f2013-03-10 19:44:48 +01003972 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003973 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01003974 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003975 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003976 goto out;
3977 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003978
3979 proto = protocol_by_family(sk->ss_family);
3980 if (!proto || !proto->connect) {
3981 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3982 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
3985 }
3986
3987 if (port1 != port2) {
3988 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
3989 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003993
3994 if (!port1) {
3995 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
3996 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004000
Willy Tarreaud5191e72010-02-09 20:50:45 +01004001 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004002 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 }
4004 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004006 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004007
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004008 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4009 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004014 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4015 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4016 err_code |= ERR_WARN;
4017
4018 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4019 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4020 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4021 }
4022 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4023 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4024 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4025 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004026 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4027 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4028 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4029 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004030 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004031 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
4035 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004036 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004038 short realport = 0;
4039 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004041 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004046 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048
4049 if (!*args[2]) {
4050 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4051 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004055
4056 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004057 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004058 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4059 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004062 }
4063
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004064 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004065 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004066 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004067 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004068
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004069 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4070 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4071 err_code |= ERR_ALERT | ERR_ABORT;
4072 goto out;
4073 }
4074
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004075 /* the servers are linked backwards first */
4076 newsrv->next = curproxy->srv;
4077 curproxy->srv = newsrv;
4078 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004079 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004080 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004082 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004083 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004084 LIST_INIT(&newsrv->pendconns);
4085 do_check = 0;
4086 newsrv->state = SRV_RUNNING; /* early server setup */
4087 newsrv->last_change = now.tv_sec;
4088 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004090 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004091 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 * - IP: => port=+0, relative
4093 * - IP:N => port=N, absolute
4094 * - IP:+N => port=+N, relative
4095 * - IP:-N => port=-N, relative
4096 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004097 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004098 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004099 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004100 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004101 goto out;
4102 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004103
4104 proto = protocol_by_family(sk->ss_family);
4105 if (!proto || !proto->connect) {
4106 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4107 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004111
4112 if (!port1 || !port2) {
4113 /* no port specified, +offset, -offset */
4114 newsrv->state |= SRV_MAPPORTS;
4115 }
4116 else if (port1 != port2) {
4117 /* port range */
4118 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4119 file, linenum, args[0], args[1], args[2]);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122 }
4123 else {
4124 /* used by checks */
4125 realport = port1;
4126 }
4127
Willy Tarreaud5191e72010-02-09 20:50:45 +01004128 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004129 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4130 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004131
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004132 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004133 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4134 file, linenum, newsrv->addr.ss_family, args[2]);
4135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
4137 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004138
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004139 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004140 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004141 newsrv->inter = curproxy->defsrv.inter;
4142 newsrv->fastinter = curproxy->defsrv.fastinter;
4143 newsrv->downinter = curproxy->defsrv.downinter;
4144 newsrv->rise = curproxy->defsrv.rise;
4145 newsrv->fall = curproxy->defsrv.fall;
4146 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4147 newsrv->minconn = curproxy->defsrv.minconn;
4148 newsrv->maxconn = curproxy->defsrv.maxconn;
4149 newsrv->slowstart = curproxy->defsrv.slowstart;
4150 newsrv->onerror = curproxy->defsrv.onerror;
4151 newsrv->consecutive_errors_limit
4152 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004153#ifdef OPENSSL
4154 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4155#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004156 newsrv->uweight = newsrv->iweight
4157 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004159 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004161 cur_arg = 3;
4162 } else {
4163 newsrv = &curproxy->defsrv;
4164 cur_arg = 1;
4165 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004166
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004168 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 newsrv->cookie = strdup(args[cur_arg + 1]);
4170 newsrv->cklen = strlen(args[cur_arg + 1]);
4171 cur_arg += 2;
4172 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004173 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004174 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4175 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4176 cur_arg += 2;
4177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004179 if (!*args[cur_arg + 1]) {
4180 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4181 file, linenum, args[cur_arg]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 }
4185
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004187 if (newsrv->rise <= 0) {
4188 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4189 file, linenum, args[cur_arg]);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192 }
4193
Willy Tarreau96839092010-03-29 10:02:24 +02004194 if (newsrv->health)
4195 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 cur_arg += 2;
4197 }
4198 else if (!strcmp(args[cur_arg], "fall")) {
4199 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004200
4201 if (!*args[cur_arg + 1]) {
4202 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4203 file, linenum, args[cur_arg]);
4204 err_code |= ERR_ALERT | ERR_FATAL;
4205 goto out;
4206 }
4207
4208 if (newsrv->fall <= 0) {
4209 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4210 file, linenum, args[cur_arg]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
4214
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 cur_arg += 2;
4216 }
4217 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004218 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4219 if (err) {
4220 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4221 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004224 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004225 if (val <= 0) {
4226 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4227 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004230 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004231 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232 cur_arg += 2;
4233 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004234 else if (!strcmp(args[cur_arg], "fastinter")) {
4235 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4236 if (err) {
4237 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4238 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004241 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004242 if (val <= 0) {
4243 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4244 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004247 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004248 newsrv->fastinter = val;
4249 cur_arg += 2;
4250 }
4251 else if (!strcmp(args[cur_arg], "downinter")) {
4252 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4253 if (err) {
4254 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4255 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004258 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004259 if (val <= 0) {
4260 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4261 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004264 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004265 newsrv->downinter = val;
4266 cur_arg += 2;
4267 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004268 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004269 struct sockaddr_storage *sk;
4270 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004271 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004272
Willy Tarreau902636f2013-03-10 19:44:48 +01004273 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004274 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004275 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004276 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004277 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004278 goto out;
4279 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004280
4281 proto = protocol_by_family(sk->ss_family);
4282 if (!proto || !proto->connect) {
4283 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004284 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004288
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004289 if (port1 != port2) {
4290 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4291 file, linenum, args[cur_arg], args[cur_arg + 1]);
4292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
4294 }
4295
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004296 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004297 cur_arg += 2;
4298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004299 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004300 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 cur_arg += 2;
4302 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004303 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 newsrv->state |= SRV_BACKUP;
4305 cur_arg ++;
4306 }
Simon Hormanfa461682011-06-25 09:39:49 +09004307 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4308 newsrv->state |= SRV_NON_STICK;
4309 cur_arg ++;
4310 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004311 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4312 newsrv->state |= SRV_SEND_PROXY;
4313 cur_arg ++;
4314 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004315 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4316 newsrv->check.send_proxy = 1;
4317 cur_arg ++;
4318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 else if (!strcmp(args[cur_arg], "weight")) {
4320 int w;
4321 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004322 if (w < 0 || w > 256) {
4323 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004328 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 cur_arg += 2;
4330 }
4331 else if (!strcmp(args[cur_arg], "minconn")) {
4332 newsrv->minconn = atol(args[cur_arg + 1]);
4333 cur_arg += 2;
4334 }
4335 else if (!strcmp(args[cur_arg], "maxconn")) {
4336 newsrv->maxconn = atol(args[cur_arg + 1]);
4337 cur_arg += 2;
4338 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004339 else if (!strcmp(args[cur_arg], "maxqueue")) {
4340 newsrv->maxqueue = atol(args[cur_arg + 1]);
4341 cur_arg += 2;
4342 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004343 else if (!strcmp(args[cur_arg], "slowstart")) {
4344 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004345 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004346 if (err) {
4347 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4348 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004351 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004352 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004353 cur_arg += 2;
4354 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004355 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004356
4357 if (!*args[cur_arg + 1]) {
4358 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4359 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004362 }
4363
4364 newsrv->trackit = strdup(args[cur_arg + 1]);
4365
4366 cur_arg += 2;
4367 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004368 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004369 global.maxsock++;
4370 do_check = 1;
4371 cur_arg += 1;
4372 }
Willy Tarreau96839092010-03-29 10:02:24 +02004373 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4374 newsrv->state |= SRV_MAINTAIN;
4375 newsrv->state &= ~SRV_RUNNING;
4376 newsrv->health = 0;
4377 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004378 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004379 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004380 if (!strcmp(args[cur_arg + 1], "none"))
4381 newsrv->observe = HANA_OBS_NONE;
4382 else if (!strcmp(args[cur_arg + 1], "layer4"))
4383 newsrv->observe = HANA_OBS_LAYER4;
4384 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4385 if (curproxy->mode != PR_MODE_HTTP) {
4386 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4387 file, linenum, args[cur_arg + 1]);
4388 err_code |= ERR_ALERT;
4389 }
4390 newsrv->observe = HANA_OBS_LAYER7;
4391 }
4392 else {
4393 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004394 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004395 file, linenum, args[cur_arg], args[cur_arg + 1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399
4400 cur_arg += 2;
4401 }
4402 else if (!strcmp(args[cur_arg], "on-error")) {
4403 if (!strcmp(args[cur_arg + 1], "fastinter"))
4404 newsrv->onerror = HANA_ONERR_FASTINTER;
4405 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4406 newsrv->onerror = HANA_ONERR_FAILCHK;
4407 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4408 newsrv->onerror = HANA_ONERR_SUDDTH;
4409 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4410 newsrv->onerror = HANA_ONERR_MARKDWN;
4411 else {
4412 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004413 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004414 file, linenum, args[cur_arg], args[cur_arg + 1]);
4415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418
4419 cur_arg += 2;
4420 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004421 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4422 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4423 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4424 else {
4425 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4426 file, linenum, args[cur_arg], args[cur_arg + 1]);
4427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
4429 }
4430
4431 cur_arg += 2;
4432 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004433 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4434 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4435 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4436 else {
4437 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4438 file, linenum, args[cur_arg], args[cur_arg + 1]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
4442
4443 cur_arg += 2;
4444 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004445 else if (!strcmp(args[cur_arg], "error-limit")) {
4446 if (!*args[cur_arg + 1]) {
4447 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4448 file, linenum, args[cur_arg]);
4449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
4451 }
4452
4453 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4454
4455 if (newsrv->consecutive_errors_limit <= 0) {
4456 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4457 file, linenum, args[cur_arg]);
4458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
4460 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004461 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004462 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004463 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004464 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004465 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004466 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004467
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004469 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4470 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004474
Willy Tarreauef9a3602012-12-08 22:29:20 +01004475 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004476 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004477 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004478 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004479 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004481 goto out;
4482 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004483
4484 proto = protocol_by_family(sk->ss_family);
4485 if (!proto || !proto->connect) {
4486 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4487 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004491
Willy Tarreauef9a3602012-12-08 22:29:20 +01004492 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004493
4494 if (port_low != port_high) {
4495 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004496
4497 if (!port_low || !port_high) {
4498 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4499 file, linenum, args[cur_arg], args[cur_arg + 1]);
4500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
4502 }
4503
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004504 if (port_low <= 0 || port_low > 65535 ||
4505 port_high <= 0 || port_high > 65535 ||
4506 port_low > port_high) {
4507 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4508 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004511 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004512 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4513 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4514 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004515 }
4516
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004518 while (*(args[cur_arg])) {
4519 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004520#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4521#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004522 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004523 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4524 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004527 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004528#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004529 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004530 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004531 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004534 }
4535 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004536 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4537 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004538 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004539 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4540 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004541 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4542 char *name, *end;
4543
4544 name = args[cur_arg+1] + 7;
4545 while (isspace(*name))
4546 name++;
4547
4548 end = name;
4549 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4550 end++;
4551
Willy Tarreauef9a3602012-12-08 22:29:20 +01004552 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4553 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4554 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4555 newsrv->conn_src.bind_hdr_len = end - name;
4556 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4557 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4558 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004559
4560 /* now look for an occurrence number */
4561 while (isspace(*end))
4562 end++;
4563 if (*end == ',') {
4564 end++;
4565 name = end;
4566 if (*end == '-')
4567 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004568 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004569 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004570 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004571 }
4572
Willy Tarreauef9a3602012-12-08 22:29:20 +01004573 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004574 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4575 " occurrences values smaller than %d.\n",
4576 file, linenum, MAX_HDR_HISTORY);
4577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
4579 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004580 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004581 struct sockaddr_storage *sk;
4582 int port1, port2;
4583
Willy Tarreau902636f2013-03-10 19:44:48 +01004584 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004585 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004586 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004587 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004588 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004589 goto out;
4590 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004591
4592 proto = protocol_by_family(sk->ss_family);
4593 if (!proto || !proto->connect) {
4594 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4595 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
4598 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004599
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004600 if (port1 != port2) {
4601 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4602 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004606 newsrv->conn_src.tproxy_addr = *sk;
4607 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004608 }
4609 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004610#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004611 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004612#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004613 cur_arg += 2;
4614 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004615#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004616 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004617 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004620#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4621 } /* "usesrc" */
4622
4623 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4624#ifdef SO_BINDTODEVICE
4625 if (!*args[cur_arg + 1]) {
4626 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4627 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004630 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004631 free(newsrv->conn_src.iface_name);
4632 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4633 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004634 global.last_checks |= LSTCHK_NETADM;
4635#else
4636 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4637 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004640#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004641 cur_arg += 2;
4642 continue;
4643 }
4644 /* this keyword in not an option of "source" */
4645 break;
4646 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004648 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004649 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4650 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004654 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004655 static int srv_dumped;
4656 struct srv_kw *kw;
4657 char *err;
4658
4659 kw = srv_find_kw(args[cur_arg]);
4660 if (kw) {
4661 char *err = NULL;
4662 int code;
4663
4664 if (!kw->parse) {
4665 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4666 file, linenum, args[0], args[1], args[cur_arg]);
4667 cur_arg += 1 + kw->skip ;
4668 err_code |= ERR_ALERT | ERR_FATAL;
4669 goto out;
4670 }
4671
4672 if (defsrv && !kw->default_ok) {
4673 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4674 file, linenum, args[0], args[1], args[cur_arg]);
4675 cur_arg += 1 + kw->skip ;
4676 err_code |= ERR_ALERT;
4677 continue;
4678 }
4679
4680 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4681 err_code |= code;
4682
4683 if (code) {
4684 if (err && *err) {
4685 indent_msg(&err, 2);
4686 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4687 }
4688 else
4689 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4690 file, linenum, args[0], args[1], args[cur_arg]);
4691 if (code & ERR_FATAL) {
4692 free(err);
4693 cur_arg += 1 + kw->skip;
4694 goto out;
4695 }
4696 }
4697 free(err);
4698 cur_arg += 1 + kw->skip;
4699 continue;
4700 }
4701
4702 err = NULL;
4703 if (!srv_dumped) {
4704 srv_dump_kws(&err);
4705 indent_msg(&err, 4);
4706 srv_dumped = 1;
4707 }
4708
4709 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4710 file, linenum, args[0], args[1], args[cur_arg],
4711 err ? " Registered keywords :" : "", err ? err : "");
4712 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004713
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 }
4717 }
4718
4719 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004720 if (newsrv->trackit) {
4721 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4722 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004725 }
4726
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004727 /* If neither a port nor an addr was specified and no check transport
4728 * layer is forced, then the transport layer used by the checks is the
4729 * same as for the production traffic. Otherwise we use raw_sock by
4730 * default, unless one is specified.
4731 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004732 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004733#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004734 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004735#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004736 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4737 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004738 /* try to get the port from check.addr if check.port not set */
4739 if (!newsrv->check.port)
4740 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004741
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004742 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004743 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004744
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004745 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004746 /* not yet valid, because no port was set on
4747 * the server either. We'll check if we have
4748 * a known port on the first listener.
4749 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004750 struct listener *l;
4751
4752 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004753 newsrv->check.port = get_host_port(&l->addr);
4754 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004755 break;
4756 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004757 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004758 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4760 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004764
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004765 /* Allocate buffer for check requests... */
4766 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004767 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4768 err_code |= ERR_ALERT | ERR_ABORT;
4769 goto out;
4770 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004771 newsrv->check.bi->size = global.tune.chksize;
4772
4773 /* Allocate buffer for check responses... */
4774 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4775 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4776 err_code |= ERR_ALERT | ERR_ABORT;
4777 goto out;
4778 }
4779 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004780
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004781 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004782 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004783 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4784 err_code |= ERR_ALERT | ERR_ABORT;
4785 goto out;
4786 }
4787
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004788 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4789 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 newsrv->state |= SRV_CHECKED;
4791 }
4792
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004793 if (!defsrv) {
4794 if (newsrv->state & SRV_BACKUP)
4795 curproxy->srv_bck++;
4796 else
4797 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004798
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004799 newsrv->prev_state = newsrv->state;
4800 }
William Lallemanda73203e2012-03-12 12:48:57 +01004801 }
4802
4803 else if (strcmp(args[0], "unique-id-format") == 0) {
4804 if (!*(args[1])) {
4805 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
4808 }
William Lallemand3203ff42012-11-11 17:30:56 +01004809 if (*(args[2])) {
4810 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004814 free(curproxy->uniqueid_format_string);
4815 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004816 }
William Lallemanda73203e2012-03-12 12:48:57 +01004817
4818 else if (strcmp(args[0], "unique-id-header") == 0) {
4819 if (!*(args[1])) {
4820 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823 }
4824 free(curproxy->header_unique_id);
4825 curproxy->header_unique_id = strdup(args[1]);
4826 }
4827
William Lallemand723b73a2012-02-08 16:37:49 +01004828 else if (strcmp(args[0], "log-format") == 0) {
4829 if (!*(args[1])) {
4830 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
William Lallemand3203ff42012-11-11 17:30:56 +01004834 if (*(args[2])) {
4835 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004839
4840 if (curproxy->logformat_string != default_http_log_format &&
4841 curproxy->logformat_string != default_tcp_log_format &&
4842 curproxy->logformat_string != clf_http_log_format)
4843 free(curproxy->logformat_string);
4844 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 }
William Lallemand723b73a2012-02-08 16:37:49 +01004846
William Lallemand0f99e342011-10-12 17:50:54 +02004847 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4848 /* delete previous herited or defined syslog servers */
4849 struct logsrv *back;
4850
4851 if (*(args[1]) != 0) {
4852 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
4855 }
4856
William Lallemand723b73a2012-02-08 16:37:49 +01004857 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4858 LIST_DEL(&tmplogsrv->list);
4859 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004860 }
4861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004863 struct logsrv *logsrv;
4864
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004866 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004867 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004868 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004869 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004870 LIST_INIT(&node->list);
4871 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 }
4874 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004875 struct sockaddr_storage *sk;
4876 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004877
4878 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879
William Lallemand0f99e342011-10-12 17:50:54 +02004880 logsrv->facility = get_log_facility(args[2]);
4881 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
4885
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 }
4887
William Lallemand0f99e342011-10-12 17:50:54 +02004888 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004890 logsrv->level = get_log_level(args[3]);
4891 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004892 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
4895
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 }
4897 }
4898
William Lallemand0f99e342011-10-12 17:50:54 +02004899 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004900 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004901 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004902 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004903 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
4906
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004907 }
4908 }
4909
Willy Tarreau902636f2013-03-10 19:44:48 +01004910 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004911 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004912 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004913 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004914 goto out;
4915 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004916
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004917 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004918
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004919 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004920 if (port1 != port2) {
4921 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4922 file, linenum, args[0], args[1]);
4923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925 }
4926
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004927 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004928 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
William Lallemand0f99e342011-10-12 17:50:54 +02004930
4931 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
4933 else {
4934 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4935 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 }
4940 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004941 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004942 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004943 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004944 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004945
Willy Tarreau977b8e42006-12-29 14:19:17 +01004946 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004947 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004948
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004950 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4951 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004955
4956 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004957 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4958 free(curproxy->conn_src.iface_name);
4959 curproxy->conn_src.iface_name = NULL;
4960 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004961
Willy Tarreau902636f2013-03-10 19:44:48 +01004962 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004963 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004964 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004965 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004966 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004967 goto out;
4968 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004969
4970 proto = protocol_by_family(sk->ss_family);
4971 if (!proto || !proto->connect) {
4972 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004973 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
4976 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004977
4978 if (port1 != port2) {
4979 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4980 file, linenum, args[0], args[1]);
4981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
4983 }
4984
Willy Tarreauef9a3602012-12-08 22:29:20 +01004985 curproxy->conn_src.source_addr = *sk;
4986 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004987
4988 cur_arg = 2;
4989 while (*(args[cur_arg])) {
4990 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004991#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4992#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004993 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004994 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4995 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004998 }
4999#endif
5000 if (!*args[cur_arg + 1]) {
5001 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5002 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005005 }
5006
5007 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005008 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5009 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005010 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005011 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5012 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005013 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5014 char *name, *end;
5015
5016 name = args[cur_arg+1] + 7;
5017 while (isspace(*name))
5018 name++;
5019
5020 end = name;
5021 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5022 end++;
5023
Willy Tarreauef9a3602012-12-08 22:29:20 +01005024 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5025 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5026 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5027 curproxy->conn_src.bind_hdr_len = end - name;
5028 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5029 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5030 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005031
5032 /* now look for an occurrence number */
5033 while (isspace(*end))
5034 end++;
5035 if (*end == ',') {
5036 end++;
5037 name = end;
5038 if (*end == '-')
5039 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005040 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005041 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005042 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005043 }
5044
Willy Tarreauef9a3602012-12-08 22:29:20 +01005045 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005046 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5047 " occurrences values smaller than %d.\n",
5048 file, linenum, MAX_HDR_HISTORY);
5049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
5051 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005052 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005053 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005054
Willy Tarreau902636f2013-03-10 19:44:48 +01005055 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005056 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005057 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005058 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005059 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005060 goto out;
5061 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005062
5063 proto = protocol_by_family(sk->ss_family);
5064 if (!proto || !proto->connect) {
5065 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5066 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
5069 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005070
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005071 if (port1 != port2) {
5072 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5073 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
5076 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005077 curproxy->conn_src.tproxy_addr = *sk;
5078 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005079 }
5080 global.last_checks |= LSTCHK_NETADM;
5081#if !defined(CONFIG_HAP_LINUX_TPROXY)
5082 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005083#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005084#else /* no TPROXY support */
5085 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005086 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005089#endif
5090 cur_arg += 2;
5091 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005092 }
5093
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005094 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5095#ifdef SO_BINDTODEVICE
5096 if (!*args[cur_arg + 1]) {
5097 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5098 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005101 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005102 free(curproxy->conn_src.iface_name);
5103 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5104 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005105 global.last_checks |= LSTCHK_NETADM;
5106#else
5107 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5108 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005111#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005112 cur_arg += 2;
5113 continue;
5114 }
5115 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005116 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005121 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5122 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5123 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134
5135 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005136 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005137 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
5141 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005143 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005144 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005150 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005151 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 }
5155 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005157 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005158 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
5162 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005163 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005164 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005165 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005168 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005169 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005171 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005172 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005174 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005175 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005176 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005177 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005178 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005179 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005181 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005182 }
5183 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005184 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005185 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005186 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005188 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005191 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197
5198 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005199 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005200 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
5204 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005205 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005206 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005207 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005212 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005213 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005214 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005215 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
5218 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005219 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005220 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005221 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 }
5225 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005226 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005227 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005228 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005229 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005232 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005233 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005234 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005235 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005236 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005237 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005240 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005241
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 if (curproxy == &defproxy) {
5243 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005247 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005248 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 if (*(args[1]) == 0) {
5251 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005252 err_code |= ERR_ALERT | ERR_FATAL;
5253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005255
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005256 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005257 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5258 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5259 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 }
5263 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5264 }
5265 else if (*args[2]) {
5266 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5267 file, linenum, args[0], args[2]);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005272 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005273 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005274 wl->s = strdup(args[1]);
5275 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005276 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 }
5278 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5281 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005285
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005287 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005288 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005289 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 }
5292 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005294 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005295 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005296 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
5299 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005301 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005302 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005303 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
5306 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5309 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005315 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005316 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 }
5320 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005322 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005323 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005324 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
5327 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005329 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005330 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005331 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 }
5334 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005335 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005336
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 if (curproxy == &defproxy) {
5338 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005342 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005343 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344
Willy Tarreaubaaee002006-06-26 02:48:02 +02005345 if (*(args[1]) == 0) {
5346 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 }
5350
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005351 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005352 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5353 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5354 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357 }
5358 err_code |= warnif_cond_requires_req(cond, file, linenum);
5359 }
5360 else if (*args[2]) {
5361 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5362 file, linenum, args[0], args[2]);
5363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
5365 }
5366
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005367 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005368 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005369 wl->s = strdup(args[1]);
5370 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 }
5372 else if (!strcmp(args[0], "errorloc") ||
5373 !strcmp(args[0], "errorloc302") ||
5374 !strcmp(args[0], "errorloc303")) { /* error location */
5375 int errnum, errlen;
5376 char *err;
5377
Willy Tarreau977b8e42006-12-29 14:19:17 +01005378 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005380
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005382 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385 }
5386
5387 errnum = atol(args[1]);
5388 if (!strcmp(args[0], "errorloc303")) {
5389 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5390 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5391 } else {
5392 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5393 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5394 }
5395
Willy Tarreau0f772532006-12-23 20:51:41 +01005396 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5397 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005398 chunk_destroy(&curproxy->errmsg[rc]);
5399 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005400 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005403
5404 if (rc >= HTTP_ERR_SIZE) {
5405 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5406 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407 free(err);
5408 }
5409 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005410 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5411 int errnum, errlen, fd;
5412 char *err;
5413 struct stat stat;
5414
5415 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005416 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005417
5418 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005419 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005422 }
5423
5424 fd = open(args[2], O_RDONLY);
5425 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5426 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5427 file, linenum, args[2], args[1]);
5428 if (fd >= 0)
5429 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005432 }
5433
Willy Tarreau27a674e2009-08-17 07:23:33 +02005434 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005435 errlen = stat.st_size;
5436 } else {
5437 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005438 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005439 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005440 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005441 }
5442
5443 err = malloc(errlen); /* malloc() must succeed during parsing */
5444 errnum = read(fd, err, errlen);
5445 if (errnum != errlen) {
5446 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5447 file, linenum, args[2], args[1]);
5448 close(fd);
5449 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005452 }
5453 close(fd);
5454
5455 errnum = atol(args[1]);
5456 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5457 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005458 chunk_destroy(&curproxy->errmsg[rc]);
5459 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005460 break;
5461 }
5462 }
5463
5464 if (rc >= HTTP_ERR_SIZE) {
5465 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5466 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005467 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005468 free(err);
5469 }
5470 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005471 else if (!strcmp(args[0], "compression")) {
5472 struct comp *comp;
5473 if (curproxy->comp == NULL) {
5474 comp = calloc(1, sizeof(struct comp));
5475 curproxy->comp = comp;
5476 } else {
5477 comp = curproxy->comp;
5478 }
5479
5480 if (!strcmp(args[1], "algo")) {
5481 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005482 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005483
William Lallemand82fe75c2012-10-23 10:25:10 +02005484 cur_arg = 2;
5485 if (!*args[cur_arg]) {
5486 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5487 file, linenum, args[0]);
5488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
5490 }
5491 while (*(args[cur_arg])) {
5492 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5493 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5494 file, linenum, args[0], args[cur_arg]);
5495 err_code |= ERR_ALERT | ERR_FATAL;
5496 goto out;
5497 }
William Lallemand552df672012-11-07 13:21:47 +01005498 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5499 curproxy->comp->algos->end(&ctx);
5500 } else {
5501 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5502 file, linenum, args[0], args[cur_arg]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005506 cur_arg ++;
5507 continue;
5508 }
5509 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005510 else if (!strcmp(args[1], "offload")) {
5511 comp->offload = 1;
5512 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005513 else if (!strcmp(args[1], "type")) {
5514 int cur_arg;
5515 cur_arg = 2;
5516 if (!*args[cur_arg]) {
5517 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5518 file, linenum, args[0]);
5519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
5521 }
5522 while (*(args[cur_arg])) {
5523 comp_append_type(comp, args[cur_arg]);
5524 cur_arg ++;
5525 continue;
5526 }
5527 }
5528 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005529 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005530 file, linenum, args[0]);
5531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 }
5534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005536 struct cfg_kw_list *kwl;
5537 int index;
5538
5539 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5540 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5541 if (kwl->kw[index].section != CFG_LISTEN)
5542 continue;
5543 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5544 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005545 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005546 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005547 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005550 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005551 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005552 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005553 err_code |= ERR_WARN;
5554 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005555 }
Willy Tarreau93893792009-07-23 13:19:11 +02005556 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005557 }
5558 }
5559 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005560
Willy Tarreau6daf3432008-01-22 16:44:08 +01005561 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 }
Willy Tarreau93893792009-07-23 13:19:11 +02005565 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005566 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005567 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568}
5569
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005570int
5571cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5572{
5573
5574 int err_code = 0;
5575 const char *err;
5576
5577 if (!strcmp(args[0], "userlist")) { /* new userlist */
5578 struct userlist *newul;
5579
5580 if (!*args[1]) {
5581 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5582 file, linenum, args[0]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
5586
5587 err = invalid_char(args[1]);
5588 if (err) {
5589 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5590 file, linenum, *err, args[0], args[1]);
5591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
5593 }
5594
5595 for (newul = userlist; newul; newul = newul->next)
5596 if (!strcmp(newul->name, args[1])) {
5597 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5598 file, linenum, args[1]);
5599 err_code |= ERR_WARN;
5600 goto out;
5601 }
5602
5603 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5604 if (!newul) {
5605 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5606 err_code |= ERR_ALERT | ERR_ABORT;
5607 goto out;
5608 }
5609
5610 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5611 newul->name = strdup(args[1]);
5612
5613 if (!newul->groupusers | !newul->name) {
5614 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5615 err_code |= ERR_ALERT | ERR_ABORT;
5616 goto out;
5617 }
5618
5619 newul->next = userlist;
5620 userlist = newul;
5621
5622 } else if (!strcmp(args[0], "group")) { /* new group */
5623 int cur_arg, i;
5624 const char *err;
5625
5626 if (!*args[1]) {
5627 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5628 file, linenum, args[0]);
5629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
5631 }
5632
5633 err = invalid_char(args[1]);
5634 if (err) {
5635 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5636 file, linenum, *err, args[0], args[1]);
5637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
5639 }
5640
5641 for(i = 0; i < userlist->grpcnt; i++)
5642 if (!strcmp(userlist->groups[i], args[1])) {
5643 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5644 file, linenum, args[1], userlist->name);
5645 err_code |= ERR_ALERT;
5646 goto out;
5647 }
5648
5649 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5650 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5651 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5652 err_code |= ERR_ALERT | ERR_FATAL;
5653 goto out;
5654 }
5655
5656 cur_arg = 2;
5657
5658 while (*args[cur_arg]) {
5659 if (!strcmp(args[cur_arg], "users")) {
5660 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5661 cur_arg += 2;
5662 continue;
5663 } else {
5664 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5665 file, linenum, args[0]);
5666 err_code |= ERR_ALERT | ERR_FATAL;
5667 goto out;
5668 }
5669 }
5670
5671 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5672 } else if (!strcmp(args[0], "user")) { /* new user */
5673 struct auth_users *newuser;
5674 int cur_arg;
5675
5676 if (!*args[1]) {
5677 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5678 file, linenum, args[0]);
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
5681 }
5682
5683 for (newuser = userlist->users; newuser; newuser = newuser->next)
5684 if (!strcmp(newuser->user, args[1])) {
5685 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5686 file, linenum, args[1], userlist->name);
5687 err_code |= ERR_ALERT;
5688 goto out;
5689 }
5690
5691 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5692 if (!newuser) {
5693 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5694 err_code |= ERR_ALERT | ERR_ABORT;
5695 goto out;
5696 }
5697
5698 newuser->user = strdup(args[1]);
5699
5700 newuser->next = userlist->users;
5701 userlist->users = newuser;
5702
5703 cur_arg = 2;
5704
5705 while (*args[cur_arg]) {
5706 if (!strcmp(args[cur_arg], "password")) {
5707#ifndef CONFIG_HAP_CRYPT
5708 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5709 file, linenum);
5710 err_code |= ERR_ALERT;
5711#endif
5712 newuser->pass = strdup(args[cur_arg + 1]);
5713 cur_arg += 2;
5714 continue;
5715 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5716 newuser->pass = strdup(args[cur_arg + 1]);
5717 newuser->flags |= AU_O_INSECURE;
5718 cur_arg += 2;
5719 continue;
5720 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005721 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005722 cur_arg += 2;
5723 continue;
5724 } else {
5725 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5726 file, linenum, args[0]);
5727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
5729 }
5730 }
5731 } else {
5732 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5733 err_code |= ERR_ALERT | ERR_FATAL;
5734 }
5735
5736out:
5737 return err_code;
5738}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739
5740/*
5741 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005742 * Returns the error code, 0 if OK, or any combination of :
5743 * - ERR_ABORT: must abort ASAP
5744 * - ERR_FATAL: we can continue parsing but not start the service
5745 * - ERR_WARN: a warning has been emitted
5746 * - ERR_ALERT: an alert has been emitted
5747 * Only the two first ones can stop processing, the two others are just
5748 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005750int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005752 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 FILE *f;
5754 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005756 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 if ((f=fopen(file,"r")) == NULL)
5759 return -1;
5760
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005761 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005762 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005763 char *end;
5764 char *args[MAX_LINE_ARGS + 1];
5765 char *line = thisline;
5766
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 linenum++;
5768
5769 end = line + strlen(line);
5770
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005771 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5772 /* Check if we reached the limit and the last char is not \n.
5773 * Watch out for the last line without the terminating '\n'!
5774 */
5775 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005776 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005777 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005778 }
5779
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005781 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 line++;
5783
5784 arg = 0;
5785 args[arg] = line;
5786
5787 while (*line && arg < MAX_LINE_ARGS) {
5788 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5789 * C equivalent value. Other combinations left unchanged (eg: \1).
5790 */
5791 if (*line == '\\') {
5792 int skip = 0;
5793 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5794 *line = line[1];
5795 skip = 1;
5796 }
5797 else if (line[1] == 'r') {
5798 *line = '\r';
5799 skip = 1;
5800 }
5801 else if (line[1] == 'n') {
5802 *line = '\n';
5803 skip = 1;
5804 }
5805 else if (line[1] == 't') {
5806 *line = '\t';
5807 skip = 1;
5808 }
5809 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005810 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 unsigned char hex1, hex2;
5812 hex1 = toupper(line[2]) - '0';
5813 hex2 = toupper(line[3]) - '0';
5814 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5815 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5816 *line = (hex1<<4) + hex2;
5817 skip = 3;
5818 }
5819 else {
5820 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005821 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 }
5823 }
5824 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005825 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826 end -= skip;
5827 }
5828 line++;
5829 }
5830 else if (*line == '#' || *line == '\n' || *line == '\r') {
5831 /* end of string, end of loop */
5832 *line = 0;
5833 break;
5834 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005835 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005837 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005838 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 line++;
5840 args[++arg] = line;
5841 }
5842 else {
5843 line++;
5844 }
5845 }
5846
5847 /* empty line */
5848 if (!**args)
5849 continue;
5850
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005851 if (*line) {
5852 /* we had to stop due to too many args.
5853 * Let's terminate the string, print the offending part then cut the
5854 * last arg.
5855 */
5856 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5857 line++;
5858 *line = '\0';
5859
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005860 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005861 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005862 err_code |= ERR_ALERT | ERR_FATAL;
5863 args[arg] = line;
5864 }
5865
Willy Tarreau540abe42007-05-02 20:50:16 +02005866 /* zero out remaining args and ensure that at least one entry
5867 * is zeroed out.
5868 */
5869 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 args[arg] = line;
5871 }
5872
Willy Tarreau3842f002009-06-14 11:39:52 +02005873 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005874 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005875 char *tmp;
5876
Willy Tarreau3842f002009-06-14 11:39:52 +02005877 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005878 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005879 for (arg=0; *args[arg+1]; arg++)
5880 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005881 *tmp = '\0'; // fix the next arg to \0
5882 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005883 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005884 else if (!strcmp(args[0], "default")) {
5885 kwm = KWM_DEF;
5886 for (arg=0; *args[arg+1]; arg++)
5887 args[arg] = args[arg+1]; // shift args after inversion
5888 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005889
William Lallemand0f99e342011-10-12 17:50:54 +02005890 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5891 strcmp(args[0], "log") != 0) {
5892 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005893 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005894 }
5895
Willy Tarreau977b8e42006-12-29 14:19:17 +01005896 if (!strcmp(args[0], "listen") ||
5897 !strcmp(args[0], "frontend") ||
5898 !strcmp(args[0], "backend") ||
5899 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005900 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005902 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005903 cursection = strdup(args[0]);
5904 }
5905 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005907 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005908 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005909 }
5910 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005911 confsect = CFG_USERLIST;
5912 free(cursection);
5913 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005914 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005915 else if (!strcmp(args[0], "peers")) {
5916 confsect = CFG_PEERS;
5917 free(cursection);
5918 cursection = strdup(args[0]);
5919 }
5920
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921 /* else it's a section keyword */
5922
5923 switch (confsect) {
5924 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005925 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 break;
5927 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005928 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005929 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005930 case CFG_USERLIST:
5931 err_code |= cfg_parse_users(file, linenum, args, kwm);
5932 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005933 case CFG_PEERS:
5934 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5935 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005937 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005938 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005940
5941 if (err_code & ERR_ABORT)
5942 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005943 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005944 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005945 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005946 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005947 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005948}
5949
Willy Tarreaubb925012009-07-23 13:36:36 +02005950/*
5951 * Returns the error code, 0 if OK, or any combination of :
5952 * - ERR_ABORT: must abort ASAP
5953 * - ERR_FATAL: we can continue parsing but not start the service
5954 * - ERR_WARN: a warning has been emitted
5955 * - ERR_ALERT: an alert has been emitted
5956 * Only the two first ones can stop processing, the two others are just
5957 * indicators.
5958 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005959int check_config_validity()
5960{
5961 int cfgerr = 0;
5962 struct proxy *curproxy = NULL;
5963 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005964 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005965 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005966 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005967 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005969 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 /*
5971 * Now, check for the integrity of all that we have collected.
5972 */
5973
5974 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005975 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976
Willy Tarreau193b8c62012-11-22 00:17:38 +01005977 if (!global.tune.max_http_hdr)
5978 global.tune.max_http_hdr = MAX_HTTP_HDR;
5979
5980 if (!global.tune.cookie_len)
5981 global.tune.cookie_len = CAPTURE_LEN;
5982
5983 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5984
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005985 /* first, we will invert the proxy list order */
5986 curproxy = NULL;
5987 while (proxy) {
5988 struct proxy *next;
5989
5990 next = proxy->next;
5991 proxy->next = curproxy;
5992 curproxy = proxy;
5993 if (!next)
5994 break;
5995 proxy = next;
5996 }
5997
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005999 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006000 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006001 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006002 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006003 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006004 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006005 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006006
Willy Tarreau050536d2012-10-04 08:47:34 +02006007 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006008 /* proxy ID not set, use automatic numbering with first
6009 * spare entry starting with next_pxid.
6010 */
6011 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6012 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6013 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006014 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006015 next_pxid++;
6016
Willy Tarreau55ea7572007-06-17 19:56:27 +02006017
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006019 /* ensure we don't keep listeners uselessly bound */
6020 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 curproxy = curproxy->next;
6022 continue;
6023 }
6024
Willy Tarreau16a21472012-11-19 12:39:59 +01006025 /* number of processes this proxy is bound to */
6026 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6027
Willy Tarreauff01a212009-03-15 13:46:16 +01006028 switch (curproxy->mode) {
6029 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006030 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006031 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006032 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6033 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006034 cfgerr++;
6035 }
6036
6037 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006038 Warning("config : servers will be ignored for %s '%s'.\n",
6039 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006040 break;
6041
6042 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006043 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006044 break;
6045
6046 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006047 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006048 break;
6049 }
6050
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006051 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006052 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006053 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006054 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6055 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006056 cfgerr++;
6057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006059 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006060 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6061 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006062 cfgerr++;
6063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006064#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006065 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006066 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6067 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006068 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006069 }
6070 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006071 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006072 /* If no LB algo is set in a backend, and we're not in
6073 * transparent mode, dispatch mode nor proxy mode, we
6074 * want to use balance roundrobin by default.
6075 */
6076 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6077 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078 }
6079 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006080
Willy Tarreau1620ec32011-08-06 17:05:02 +02006081 if (curproxy->options & PR_O_DISPATCH)
6082 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6083 else if (curproxy->options & PR_O_HTTP_PROXY)
6084 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6085 else if (curproxy->options & PR_O_TRANSP)
6086 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006087
Willy Tarreau1620ec32011-08-06 17:05:02 +02006088 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6089 if (curproxy->options & PR_O_DISABLE404) {
6090 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6091 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6092 err_code |= ERR_WARN;
6093 curproxy->options &= ~PR_O_DISABLE404;
6094 }
6095 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6096 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6097 "send-state", proxy_type_str(curproxy), curproxy->id);
6098 err_code |= ERR_WARN;
6099 curproxy->options &= ~PR_O2_CHK_SNDST;
6100 }
Willy Tarreauef781042010-01-27 11:53:01 +01006101 }
6102
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006103 /* if a default backend was specified, let's find it */
6104 if (curproxy->defbe.name) {
6105 struct proxy *target;
6106
Alex Williams96532db2009-11-01 21:27:13 -05006107 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006108 if (!target) {
6109 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6110 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006111 cfgerr++;
6112 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006113 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6114 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006115 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006116 } else {
6117 free(curproxy->defbe.name);
6118 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006119 /* we force the backend to be present on at least all of
6120 * the frontend's processes.
6121 */
6122 target->bind_proc = curproxy->bind_proc ?
6123 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006124
6125 /* Emit a warning if this proxy also has some servers */
6126 if (curproxy->srv) {
6127 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6128 curproxy->id);
6129 err_code |= ERR_WARN;
6130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 }
6132 }
6133
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006134 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006135 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6136 /* map jump target for ACT_SETBE in req_rep chain */
6137 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006138 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006139 struct proxy *target;
6140
Willy Tarreaua496b602006-12-17 23:15:24 +01006141 if (exp->action != ACT_SETBE)
6142 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006143
Alex Williams96532db2009-11-01 21:27:13 -05006144 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006145 if (!target) {
6146 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6147 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006148 cfgerr++;
6149 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006150 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6151 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006152 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006153 } else {
6154 free((void *)exp->replace);
6155 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006156 /* we force the backend to be present on at least all of
6157 * the frontend's processes.
6158 */
6159 target->bind_proc = curproxy->bind_proc ?
6160 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006161 }
6162 }
6163 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006164
6165 /* find the target proxy for 'use_backend' rules */
6166 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006167 struct proxy *target;
6168
Alex Williams96532db2009-11-01 21:27:13 -05006169 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006170
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006171 if (!target) {
6172 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6173 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006174 cfgerr++;
6175 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006176 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6177 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006178 cfgerr++;
6179 } else {
6180 free((void *)rule->be.name);
6181 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006182 /* we force the backend to be present on at least all of
6183 * the frontend's processes.
6184 */
6185 target->bind_proc = curproxy->bind_proc ?
6186 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006187 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006188 }
6189
6190 /* find the target proxy for 'use_backend' rules */
6191 list_for_each_entry(srule, &curproxy->server_rules, list) {
6192 struct server *target = findserver(curproxy, srule->srv.name);
6193
6194 if (!target) {
6195 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6196 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6197 cfgerr++;
6198 continue;
6199 }
6200 free((void *)srule->srv.name);
6201 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006202 }
6203
Emeric Brunb982a3d2010-01-04 15:45:53 +01006204 /* find the target table for 'stick' rules */
6205 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6206 struct proxy *target;
6207
Emeric Brun1d33b292010-01-04 15:47:17 +01006208 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6209 if (mrule->flags & STK_IS_STORE)
6210 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6211
Emeric Brunb982a3d2010-01-04 15:45:53 +01006212 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006213 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006214 else
6215 target = curproxy;
6216
6217 if (!target) {
6218 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6219 curproxy->id, mrule->table.name);
6220 cfgerr++;
6221 }
6222 else if (target->table.size == 0) {
6223 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6224 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6225 cfgerr++;
6226 }
Willy Tarreau12785782012-04-27 21:37:17 +02006227 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6228 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006229 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6230 cfgerr++;
6231 }
6232 else {
6233 free((void *)mrule->table.name);
6234 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006235 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006236 }
6237 }
6238
6239 /* find the target table for 'store response' rules */
6240 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6241 struct proxy *target;
6242
Emeric Brun1d33b292010-01-04 15:47:17 +01006243 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6244
Emeric Brunb982a3d2010-01-04 15:45:53 +01006245 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006246 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006247 else
6248 target = curproxy;
6249
6250 if (!target) {
6251 Alert("Proxy '%s': unable to find store table '%s'.\n",
6252 curproxy->id, mrule->table.name);
6253 cfgerr++;
6254 }
6255 else if (target->table.size == 0) {
6256 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6257 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6258 cfgerr++;
6259 }
Willy Tarreau12785782012-04-27 21:37:17 +02006260 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6261 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006262 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6263 cfgerr++;
6264 }
6265 else {
6266 free((void *)mrule->table.name);
6267 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006268 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006269 }
6270 }
6271
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006272 /* find the target table for 'tcp-request' layer 4 rules */
6273 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6274 struct proxy *target;
6275
Willy Tarreau56123282010-08-06 19:06:56 +02006276 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006277 continue;
6278
6279 if (trule->act_prm.trk_ctr.table.n)
6280 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6281 else
6282 target = curproxy;
6283
6284 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006285 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6286 curproxy->id, trule->act_prm.trk_ctr.table.n,
6287 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006288 cfgerr++;
6289 }
6290 else if (target->table.size == 0) {
6291 Alert("Proxy '%s': table '%s' used but not configured.\n",
6292 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6293 cfgerr++;
6294 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006295 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6296 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6297 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6298 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6299 cfgerr++;
6300 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006301 else {
6302 free(trule->act_prm.trk_ctr.table.n);
6303 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006304 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006305 * to pass a list of counters to track and allocate them right here using
6306 * stktable_alloc_data_type().
6307 */
6308 }
6309 }
6310
Willy Tarreaud1f96522010-08-03 19:34:32 +02006311 /* find the target table for 'tcp-request' layer 6 rules */
6312 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6313 struct proxy *target;
6314
Willy Tarreau56123282010-08-06 19:06:56 +02006315 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006316 continue;
6317
6318 if (trule->act_prm.trk_ctr.table.n)
6319 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6320 else
6321 target = curproxy;
6322
6323 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006324 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6325 curproxy->id, trule->act_prm.trk_ctr.table.n,
6326 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006327 cfgerr++;
6328 }
6329 else if (target->table.size == 0) {
6330 Alert("Proxy '%s': table '%s' used but not configured.\n",
6331 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6332 cfgerr++;
6333 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006334 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6335 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6336 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6337 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6338 cfgerr++;
6339 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006340 else {
6341 free(trule->act_prm.trk_ctr.table.n);
6342 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006343 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006344 * to pass a list of counters to track and allocate them right here using
6345 * stktable_alloc_data_type().
6346 */
6347 }
6348 }
6349
Emeric Brun32da3c42010-09-23 18:39:19 +02006350 if (curproxy->table.peers.name) {
6351 struct peers *curpeers = peers;
6352
6353 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6354 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6355 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006356 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006357 break;
6358 }
6359 }
6360
6361 if (!curpeers) {
6362 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6363 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006364 free((void *)curproxy->table.peers.name);
6365 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006366 cfgerr++;
6367 }
6368 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006369 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6370 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006371 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006372 cfgerr++;
6373 }
6374 }
6375
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006376 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006377 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006378 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6379 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6380 "proxy", curproxy->id);
6381 cfgerr++;
6382 goto out_uri_auth_compat;
6383 }
6384
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006385 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006386 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006387 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006388 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006389
Willy Tarreau95fa4692010-02-01 13:05:50 +01006390 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6391 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006392
6393 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006394 uri_auth_compat_req[i++] = "realm";
6395 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6396 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006397
Willy Tarreau95fa4692010-02-01 13:05:50 +01006398 uri_auth_compat_req[i++] = "unless";
6399 uri_auth_compat_req[i++] = "{";
6400 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6401 uri_auth_compat_req[i++] = "}";
6402 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006403
Willy Tarreauff011f22011-01-06 17:51:27 +01006404 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6405 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006406 cfgerr++;
6407 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006408 }
6409
Willy Tarreauff011f22011-01-06 17:51:27 +01006410 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006411
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006412 if (curproxy->uri_auth->auth_realm) {
6413 free(curproxy->uri_auth->auth_realm);
6414 curproxy->uri_auth->auth_realm = NULL;
6415 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006416
6417 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006418 }
6419out_uri_auth_compat:
6420
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006421 cfgerr += acl_find_targets(curproxy);
6422
Willy Tarreau2738a142006-07-08 17:28:09 +02006423 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006424 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006425 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006426 (!curproxy->timeout.connect ||
6427 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006428 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006429 " | While not properly invalid, you will certainly encounter various problems\n"
6430 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006431 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006432 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006433 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006434 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006435
Willy Tarreau1fa31262007-12-03 00:36:16 +01006436 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6437 * We must still support older configurations, so let's find out whether those
6438 * parameters have been set or must be copied from contimeouts.
6439 */
6440 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006441 if (!curproxy->timeout.tarpit ||
6442 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006443 /* tarpit timeout not set. We search in the following order:
6444 * default.tarpit, curr.connect, default.connect.
6445 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006446 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006447 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006448 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006449 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006450 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006451 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006452 }
6453 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006454 (!curproxy->timeout.queue ||
6455 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006456 /* queue timeout not set. We search in the following order:
6457 * default.queue, curr.connect, default.connect.
6458 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006459 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006460 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006461 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006462 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006463 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006464 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006465 }
6466 }
6467
Willy Tarreau1620ec32011-08-06 17:05:02 +02006468 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006469 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6470 curproxy->check_req = (char *)malloc(curproxy->check_len);
6471 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006472 }
6473
Willy Tarreau193b8c62012-11-22 00:17:38 +01006474 /* ensure that cookie capture length is not too large */
6475 if (curproxy->capture_len >= global.tune.cookie_len) {
6476 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6477 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6478 err_code |= ERR_WARN;
6479 curproxy->capture_len = global.tune.cookie_len - 1;
6480 }
6481
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006482 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006483 if (curproxy->nb_req_cap) {
6484 if (curproxy->mode == PR_MODE_HTTP) {
6485 curproxy->req_cap_pool = create_pool("ptrcap",
6486 curproxy->nb_req_cap * sizeof(char *),
6487 MEM_F_SHARED);
6488 } else {
6489 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6490 proxy_type_str(curproxy), curproxy->id);
6491 err_code |= ERR_WARN;
6492 curproxy->to_log &= ~LW_REQHDR;
6493 curproxy->nb_req_cap = 0;
6494 }
6495 }
6496
6497 if (curproxy->nb_rsp_cap) {
6498 if (curproxy->mode == PR_MODE_HTTP) {
6499 curproxy->rsp_cap_pool = create_pool("ptrcap",
6500 curproxy->nb_rsp_cap * sizeof(char *),
6501 MEM_F_SHARED);
6502 } else {
6503 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6504 proxy_type_str(curproxy), curproxy->id);
6505 err_code |= ERR_WARN;
6506 curproxy->to_log &= ~LW_REQHDR;
6507 curproxy->nb_rsp_cap = 0;
6508 }
6509 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006510
Willy Tarreau196729e2012-05-31 19:30:26 +02006511 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006512 if (!(curproxy->cap & PR_CAP_FE)) {
6513 if (curproxy->logformat_string != default_http_log_format &&
6514 curproxy->logformat_string != default_tcp_log_format &&
6515 curproxy->logformat_string != clf_http_log_format)
6516 free(curproxy->logformat_string);
6517 curproxy->logformat_string = NULL;
6518 }
6519
Willy Tarreau196729e2012-05-31 19:30:26 +02006520 if (curproxy->logformat_string)
Willy Tarreau434c57c2013-01-08 01:10:24 +01006521 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
6522 SMP_VAL_FE_LOG_END);
Willy Tarreau196729e2012-05-31 19:30:26 +02006523
6524 if (curproxy->uniqueid_format_string)
Willy Tarreau434c57c2013-01-08 01:10:24 +01006525 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
6526 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau196729e2012-05-31 19:30:26 +02006527
Willy Tarreaubaaee002006-06-26 02:48:02 +02006528 /* first, we will invert the servers list order */
6529 newsrv = NULL;
6530 while (curproxy->srv) {
6531 struct server *next;
6532
6533 next = curproxy->srv->next;
6534 curproxy->srv->next = newsrv;
6535 newsrv = curproxy->srv;
6536 if (!next)
6537 break;
6538 curproxy->srv = next;
6539 }
6540
Willy Tarreaudd701652010-05-25 23:03:02 +02006541 /* assign automatic UIDs to servers which don't have one yet */
6542 next_id = 1;
6543 newsrv = curproxy->srv;
6544 while (newsrv != NULL) {
6545 if (!newsrv->puid) {
6546 /* server ID not set, use automatic numbering with first
6547 * spare entry starting with next_svid.
6548 */
6549 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6550 newsrv->conf.id.key = newsrv->puid = next_id;
6551 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6552 }
6553 next_id++;
6554 newsrv = newsrv->next;
6555 }
6556
Willy Tarreau20697042007-11-15 23:26:18 +01006557 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006558 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559
Willy Tarreau62c3be22012-01-20 13:12:32 +01006560 /*
6561 * If this server supports a maxconn parameter, it needs a dedicated
6562 * tasks to fill the emptied slots when a connection leaves.
6563 * Also, resolve deferred tracking dependency if needed.
6564 */
6565 newsrv = curproxy->srv;
6566 while (newsrv != NULL) {
6567 if (newsrv->minconn > newsrv->maxconn) {
6568 /* Only 'minconn' was specified, or it was higher than or equal
6569 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6570 * this will avoid further useless expensive computations.
6571 */
6572 newsrv->maxconn = newsrv->minconn;
6573 } else if (newsrv->maxconn && !newsrv->minconn) {
6574 /* minconn was not specified, so we set it to maxconn */
6575 newsrv->minconn = newsrv->maxconn;
6576 }
6577
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006578#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006579 if (newsrv->use_ssl || newsrv->check.use_ssl)
6580 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006581#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006582
Willy Tarreau62c3be22012-01-20 13:12:32 +01006583 if (newsrv->trackit) {
6584 struct proxy *px;
6585 struct server *srv;
6586 char *pname, *sname;
6587
6588 pname = newsrv->trackit;
6589 sname = strrchr(pname, '/');
6590
6591 if (sname)
6592 *sname++ = '\0';
6593 else {
6594 sname = pname;
6595 pname = NULL;
6596 }
6597
6598 if (pname) {
6599 px = findproxy(pname, PR_CAP_BE);
6600 if (!px) {
6601 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6602 proxy_type_str(curproxy), curproxy->id,
6603 newsrv->id, pname);
6604 cfgerr++;
6605 goto next_srv;
6606 }
6607 } else
6608 px = curproxy;
6609
6610 srv = findserver(px, sname);
6611 if (!srv) {
6612 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6613 proxy_type_str(curproxy), curproxy->id,
6614 newsrv->id, sname);
6615 cfgerr++;
6616 goto next_srv;
6617 }
6618
6619 if (!(srv->state & SRV_CHECKED)) {
6620 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6621 "tracking as it does not have checks enabled.\n",
6622 proxy_type_str(curproxy), curproxy->id,
6623 newsrv->id, px->id, srv->id);
6624 cfgerr++;
6625 goto next_srv;
6626 }
6627
6628 if (curproxy != px &&
6629 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6630 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6631 "tracking: disable-on-404 option inconsistency.\n",
6632 proxy_type_str(curproxy), curproxy->id,
6633 newsrv->id, px->id, srv->id);
6634 cfgerr++;
6635 goto next_srv;
6636 }
6637
6638 /* if the other server is forced disabled, we have to do the same here */
6639 if (srv->state & SRV_MAINTAIN) {
6640 newsrv->state |= SRV_MAINTAIN;
6641 newsrv->state &= ~SRV_RUNNING;
6642 newsrv->health = 0;
6643 }
6644
6645 newsrv->track = srv;
6646 newsrv->tracknext = srv->tracknext;
6647 srv->tracknext = newsrv;
6648
6649 free(newsrv->trackit);
6650 newsrv->trackit = NULL;
6651 }
6652 next_srv:
6653 newsrv = newsrv->next;
6654 }
6655
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006656 /* We have to initialize the server lookup mechanism depending
6657 * on what LB algorithm was choosen.
6658 */
6659
6660 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6661 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6662 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006663 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6664 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6665 init_server_map(curproxy);
6666 } else {
6667 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6668 fwrr_init_server_groups(curproxy);
6669 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006670 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006671
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006672 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006673 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6674 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6675 fwlc_init_server_tree(curproxy);
6676 } else {
6677 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6678 fas_init_server_tree(curproxy);
6679 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006680 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006681
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006682 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006683 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6684 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6685 chash_init_server_tree(curproxy);
6686 } else {
6687 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6688 init_server_map(curproxy);
6689 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006690 break;
6691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006692
6693 if (curproxy->options & PR_O_LOGASAP)
6694 curproxy->to_log &= ~LW_BYTES;
6695
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006696 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006697 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006698 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6699 proxy_type_str(curproxy), curproxy->id);
6700 err_code |= ERR_WARN;
6701 }
6702
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006703 if (curproxy->mode != PR_MODE_HTTP) {
6704 int optnum;
6705
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006706 if (curproxy->uri_auth) {
6707 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6708 proxy_type_str(curproxy), curproxy->id);
6709 err_code |= ERR_WARN;
6710 curproxy->uri_auth = NULL;
6711 }
6712
Willy Tarreau87cf5142011-08-19 22:57:24 +02006713 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006714 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6715 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6716 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006717 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006718 }
6719
6720 if (curproxy->options & PR_O_ORGTO) {
6721 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6722 "originalto", proxy_type_str(curproxy), curproxy->id);
6723 err_code |= ERR_WARN;
6724 curproxy->options &= ~PR_O_ORGTO;
6725 }
6726
6727 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6728 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6729 (curproxy->cap & cfg_opts[optnum].cap) &&
6730 (curproxy->options & cfg_opts[optnum].val)) {
6731 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6732 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6733 err_code |= ERR_WARN;
6734 curproxy->options &= ~cfg_opts[optnum].val;
6735 }
6736 }
6737
6738 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6739 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6740 (curproxy->cap & cfg_opts2[optnum].cap) &&
6741 (curproxy->options2 & cfg_opts2[optnum].val)) {
6742 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6743 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6744 err_code |= ERR_WARN;
6745 curproxy->options2 &= ~cfg_opts2[optnum].val;
6746 }
6747 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006748
Willy Tarreauefa5f512010-03-30 20:13:29 +02006749#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006750 if (curproxy->conn_src.bind_hdr_occ) {
6751 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006752 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006753 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006754 err_code |= ERR_WARN;
6755 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006756#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006757 }
6758
Willy Tarreaubaaee002006-06-26 02:48:02 +02006759 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006760 * ensure that we're not cross-dressing a TCP server into HTTP.
6761 */
6762 newsrv = curproxy->srv;
6763 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006764 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006765 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6766 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006767 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006768 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006769
Willy Tarreau0cec3312011-10-31 13:49:26 +01006770 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6771 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6772 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6773 err_code |= ERR_WARN;
6774 }
6775
Willy Tarreauefa5f512010-03-30 20:13:29 +02006776#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006777 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6778 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006779 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 +01006780 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006781 err_code |= ERR_WARN;
6782 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006783#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006784 newsrv = newsrv->next;
6785 }
6786
Willy Tarreauc1a21672009-08-16 22:37:44 +02006787 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006788 if (!curproxy->accept)
6789 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006790
Willy Tarreauc1a21672009-08-16 22:37:44 +02006791 if (curproxy->tcp_req.inspect_delay ||
6792 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006793 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006794
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006795 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006796 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006797 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006798 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006799
6800 /* both TCP and HTTP must check switching rules */
6801 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6802 }
6803
6804 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006805 if (curproxy->tcp_req.inspect_delay ||
6806 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6807 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6808
Emeric Brun97679e72010-09-23 17:56:44 +02006809 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6810 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6811
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006812 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006813 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006814 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006815 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006816
6817 /* If the backend does requires RDP cookie persistence, we have to
6818 * enable the corresponding analyser.
6819 */
6820 if (curproxy->options2 & PR_O2_RDPC_PRST)
6821 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6822 }
6823
Emeric Brunc52962f2012-11-15 18:28:02 +01006824#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006825 /* Configure SSL for each bind line.
6826 * Note: if configuration fails at some point, the ->ctx member
6827 * remains NULL so that listeners can later detach.
6828 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006829 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006830 if (!bind_conf->is_ssl) {
6831 if (bind_conf->default_ctx) {
6832 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6833 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6834 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006835 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006836 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006837 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006838 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006839 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006840 cfgerr++;
6841 continue;
6842 }
6843
Emeric Brun4b3091e2012-09-24 15:48:52 +02006844 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006845 Alert("Unable to allocate SSL session cache.\n");
6846 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006847 continue;
6848 }
6849
Emeric Brunfc0421f2012-09-07 17:30:07 +02006850 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006851 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006852 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006853#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006854
Willy Tarreaue6b98942007-10-29 01:09:36 +01006855 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006856 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006857 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006858 if (!listener->luid) {
6859 /* listener ID not set, use automatic numbering with first
6860 * spare entry starting with next_luid.
6861 */
6862 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6863 listener->conf.id.key = listener->luid = next_id;
6864 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006865 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006866 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006867
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006868 /* enable separate counters */
6869 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6870 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006871 if (!listener->name)
6872 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006873 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006874
Willy Tarreaue6b98942007-10-29 01:09:36 +01006875 if (curproxy->options & PR_O_TCP_NOLING)
6876 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006877 if (!listener->maxconn)
6878 listener->maxconn = curproxy->maxconn;
6879 if (!listener->backlog)
6880 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006881 if (!listener->maxaccept)
6882 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6883
6884 /* we want to have an optimal behaviour on single process mode to
6885 * maximize the work at once, but in multi-process we want to keep
6886 * some fairness between processes, so we target half of the max
6887 * number of events to be balanced over all the processes the proxy
6888 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6889 * used to disable the limit.
6890 */
6891 if (listener->maxaccept > 0) {
6892 if (nbproc > 1)
6893 listener->maxaccept = (listener->maxaccept + 1) / 2;
6894 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6895 }
6896
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006897 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006898 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006899 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006900 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006901
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006902 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6903 listener->options |= LI_O_TCP_RULES;
6904
Willy Tarreaude3041d2010-05-31 10:56:17 +02006905 if (curproxy->mon_mask.s_addr)
6906 listener->options |= LI_O_CHK_MONNET;
6907
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006908 /* smart accept mode is automatic in HTTP mode */
6909 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006910 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006911 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6912 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006913 }
6914
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006915 /* Release unused SSL configs */
6916 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6917 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006918 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006919#ifdef USE_OPENSSL
6920 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006921 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006922 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006923 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006924 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006925#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006926 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006927
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006928 /* Check multi-process mode compatibility for the current proxy */
6929 if (global.nbproc > 1) {
6930 int nbproc = 0;
6931 if (curproxy->bind_proc) {
6932 int proc;
6933 for (proc = 0; proc < global.nbproc; proc++) {
6934 if (curproxy->bind_proc & (1 << proc)) {
6935 nbproc++;
6936 }
6937 }
6938 } else {
6939 nbproc = global.nbproc;
6940 }
6941 if (curproxy->table.peers.name) {
6942 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6943 curproxy->id);
6944 cfgerr++;
6945 }
6946 if (nbproc > 1) {
6947 if (curproxy->uri_auth) {
6948 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6949 curproxy->id);
6950 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6951 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6952 curproxy->id);
6953 }
6954 }
6955 if (curproxy->appsession_name) {
6956 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6957 curproxy->id);
6958 }
6959 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6960 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6961 curproxy->id);
6962 }
6963 }
6964 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006965
6966 /* create the task associated with the proxy */
6967 curproxy->task = task_new();
6968 if (curproxy->task) {
6969 curproxy->task->context = curproxy;
6970 curproxy->task->process = manage_proxy;
6971 /* no need to queue, it will be done automatically if some
6972 * listener gets limited.
6973 */
6974 curproxy->task->expire = TICK_ETERNITY;
6975 } else {
6976 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6977 curproxy->id);
6978 cfgerr++;
6979 }
6980
Willy Tarreaubaaee002006-06-26 02:48:02 +02006981 curproxy = curproxy->next;
6982 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006983
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006984 /* Check multi-process mode compatibility */
6985 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006986 if (global.stats_fe && !global.stats_fe->bind_proc) {
6987 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 +01006988 }
6989 }
6990
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006991 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6992 struct auth_users *curuser;
6993 int g;
6994
6995 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6996 unsigned int group_mask = 0;
6997 char *group = NULL;
6998
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006999 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007000 continue;
7001
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007002 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007003
7004 for (g = 0; g < curuserlist->grpcnt; g++)
7005 if (!strcmp(curuserlist->groups[g], group))
7006 break;
7007
7008 if (g == curuserlist->grpcnt) {
7009 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7010 curuserlist->name, group, curuser->user);
7011 err_code |= ERR_ALERT | ERR_FATAL;
7012 goto out;
7013 }
7014
7015 group_mask |= (1 << g);
7016 }
7017
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007018 free(curuser->u.groups);
7019 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007020 }
7021
7022 for (g = 0; g < curuserlist->grpcnt; g++) {
7023 char *user = NULL;
7024
7025 if (!curuserlist->groupusers[g])
7026 continue;
7027
7028 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7029 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7030 if (!strcmp(curuser->user, user))
7031 break;
7032
7033 if (!curuser) {
7034 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7035 curuserlist->name, user, curuserlist->groups[g]);
7036 err_code |= ERR_ALERT | ERR_FATAL;
7037 goto out;
7038 }
7039
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007040 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007041 }
7042
7043 free(curuserlist->groupusers[g]);
7044 }
7045
7046 free(curuserlist->groupusers);
7047
7048#ifdef DEBUG_AUTH
7049 for (g = 0; g < curuserlist->grpcnt; g++) {
7050 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7051
7052 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007053 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007054 fprintf(stderr, " %s", curuser->user);
7055 }
7056
7057 fprintf(stderr, "\n");
7058 }
7059#endif
7060
Willy Tarreaufbb78422011-06-05 15:38:35 +02007061 }
7062
7063 /* automatically compute fullconn if not set. We must not do it in the
7064 * loop above because cross-references are not yet fully resolved.
7065 */
7066 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7067 /* If <fullconn> is not set, let's set it to 10% of the sum of
7068 * the possible incoming frontend's maxconns.
7069 */
7070 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7071 struct proxy *fe;
7072 int total = 0;
7073
7074 /* sum up the number of maxconns of frontends which
7075 * reference this backend at least once or which are
7076 * the same one ('listen').
7077 */
7078 for (fe = proxy; fe; fe = fe->next) {
7079 struct switching_rule *rule;
7080 struct hdr_exp *exp;
7081 int found = 0;
7082
7083 if (!(fe->cap & PR_CAP_FE))
7084 continue;
7085
7086 if (fe == curproxy) /* we're on a "listen" instance */
7087 found = 1;
7088
7089 if (fe->defbe.be == curproxy) /* "default_backend" */
7090 found = 1;
7091
7092 /* check if a "use_backend" rule matches */
7093 if (!found) {
7094 list_for_each_entry(rule, &fe->switching_rules, list) {
7095 if (rule->be.backend == curproxy) {
7096 found = 1;
7097 break;
7098 }
7099 }
7100 }
7101
7102 /* check if a "reqsetbe" rule matches */
7103 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7104 if (exp->action == ACT_SETBE &&
7105 (struct proxy *)exp->replace == curproxy) {
7106 found = 1;
7107 break;
7108 }
7109 }
7110
7111 /* now we've checked all possible ways to reference a backend
7112 * from a frontend.
7113 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007114 if (!found)
7115 continue;
7116 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007117 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007118 /* we have the sum of the maxconns in <total>. We only
7119 * keep 10% of that sum to set the default fullconn, with
7120 * a hard minimum of 1 (to avoid a divide by zero).
7121 */
7122 curproxy->fullconn = (total + 9) / 10;
7123 if (!curproxy->fullconn)
7124 curproxy->fullconn = 1;
7125 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007126 }
7127
Willy Tarreau056f5682010-06-06 15:51:11 +02007128 /* initialize stick-tables on backend capable proxies. This must not
7129 * be done earlier because the data size may be discovered while parsing
7130 * other proxies.
7131 */
7132 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007133 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007134
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007135 /*
7136 * Recount currently required checks.
7137 */
7138
7139 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7140 int optnum;
7141
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007142 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7143 if (curproxy->options & cfg_opts[optnum].val)
7144 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007145
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007146 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7147 if (curproxy->options2 & cfg_opts2[optnum].val)
7148 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007149 }
7150
Willy Tarreau122541c2011-09-07 21:24:49 +02007151 if (peers) {
7152 struct peers *curpeers = peers, **last;
7153 struct peer *p, *pb;
7154
7155 /* Remove all peers sections which don't have a valid listener.
7156 * This can happen when a peers section is never referenced and
7157 * does not contain a local peer.
7158 */
7159 last = &peers;
7160 while (*last) {
7161 curpeers = *last;
7162 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007163 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007164 last = &curpeers->next;
7165 continue;
7166 }
7167
7168 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7169 curpeers->id, localpeer);
7170
7171 p = curpeers->remote;
7172 while (p) {
7173 pb = p->next;
7174 free(p->id);
7175 free(p);
7176 p = pb;
7177 }
7178
7179 /* Destroy and unlink this curpeers section.
7180 * Note: curpeers is backed up into *last.
7181 */
7182 free(curpeers->id);
7183 curpeers = curpeers->next;
7184 free(*last);
7185 *last = curpeers;
7186 }
7187 }
7188
Willy Tarreau34eb6712011-10-24 18:15:04 +02007189 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007190 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007191 MEM_F_SHARED);
7192
Willy Tarreaubb925012009-07-23 13:36:36 +02007193 if (cfgerr > 0)
7194 err_code |= ERR_ALERT | ERR_FATAL;
7195 out:
7196 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007197}
7198
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007199/*
7200 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7201 * parsing sessions.
7202 */
7203void cfg_register_keywords(struct cfg_kw_list *kwl)
7204{
7205 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7206}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007207
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007208/*
7209 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7210 */
7211void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7212{
7213 LIST_DEL(&kwl->list);
7214 LIST_INIT(&kwl->list);
7215}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007216
7217/*
7218 * Local variables:
7219 * c-indent-level: 8
7220 * c-basic-offset: 8
7221 * End:
7222 */