blob: b02bb0154dfa858b3d3a11b09efbfa1014a9e923 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100612 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200613 }
614 else if (!strcmp(args[0], "tune.maxrewrite")) {
615 if (*(args[1]) == 0) {
616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
619 }
620 global.tune.maxrewrite = atol(args[1]);
621 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
622 global.tune.maxrewrite = global.tune.bufsize / 2;
623 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100624 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
625 if (global.tune.client_rcvbuf != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT;
628 goto out;
629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
634 }
635 global.tune.client_rcvbuf = atol(args[1]);
636 }
637 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
638 if (global.tune.server_rcvbuf != 0) {
639 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT;
641 goto out;
642 }
643 if (*(args[1]) == 0) {
644 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648 global.tune.server_rcvbuf = atol(args[1]);
649 }
650 else if (!strcmp(args[0], "tune.sndbuf.client")) {
651 if (global.tune.client_sndbuf != 0) {
652 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT;
654 goto out;
655 }
656 if (*(args[1]) == 0) {
657 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT | ERR_FATAL;
659 goto out;
660 }
661 global.tune.client_sndbuf = atol(args[1]);
662 }
663 else if (!strcmp(args[0], "tune.sndbuf.server")) {
664 if (global.tune.server_sndbuf != 0) {
665 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
666 err_code |= ERR_ALERT;
667 goto out;
668 }
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 global.tune.server_sndbuf = atol(args[1]);
675 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200676 else if (!strcmp(args[0], "tune.pipesize")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.pipesize = atol(args[1]);
683 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100684 else if (!strcmp(args[0], "tune.http.cookielen")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.cookie_len = atol(args[1]) + 1;
691 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200692 else if (!strcmp(args[0], "tune.http.maxhdr")) {
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
697 }
698 global.tune.max_http_hdr = atol(args[1]);
699 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100700 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
701#ifdef USE_ZLIB
702 if (*args[1]) {
703 global.tune.zlibmemlevel = atoi(args[1]);
704 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
705 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
706 file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 } else {
711 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
712 file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716#else
717 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720#endif
721 }
722 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
723#ifdef USE_ZLIB
724 if (*args[1]) {
725 global.tune.zlibwindowsize = atoi(args[1]);
726 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
727 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
728 file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 } else {
733 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
734 file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#else
739 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742#endif
743 }
William Lallemandf3747832012-11-09 12:33:10 +0100744 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
745 if (*args[1]) {
746 global.tune.comp_maxlevel = atoi(args[1]);
747 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
748 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
749 file, linenum, args[0]);
750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
752 }
753 } else {
754 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
755 file, linenum, args[0]);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
758 }
759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 else if (!strcmp(args[0], "uid")) {
761 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200762 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200763 err_code |= ERR_ALERT;
764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765 }
766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 global.uid = atol(args[1]);
772 }
773 else if (!strcmp(args[0], "gid")) {
774 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200775 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200776 err_code |= ERR_ALERT;
777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 }
779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 }
784 global.gid = atol(args[1]);
785 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200786 /* user/group name handling */
787 else if (!strcmp(args[0], "user")) {
788 struct passwd *ha_user;
789 if (global.uid != 0) {
790 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT;
792 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200793 }
794 errno = 0;
795 ha_user = getpwnam(args[1]);
796 if (ha_user != NULL) {
797 global.uid = (int)ha_user->pw_uid;
798 }
799 else {
800 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 +0200801 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200802 }
803 }
804 else if (!strcmp(args[0], "group")) {
805 struct group *ha_group;
806 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200807 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200808 err_code |= ERR_ALERT;
809 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200810 }
811 errno = 0;
812 ha_group = getgrnam(args[1]);
813 if (ha_group != NULL) {
814 global.gid = (int)ha_group->gr_gid;
815 }
816 else {
817 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 +0200818 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200819 }
820 }
821 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 global.nbproc = atol(args[1]);
829 }
830 else if (!strcmp(args[0], "maxconn")) {
831 if (global.maxconn != 0) {
832 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200833 err_code |= ERR_ALERT;
834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 global.maxconn = atol(args[1]);
842#ifdef SYSTEM_MAXCONN
843 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
844 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);
845 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200846 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200847 }
848#endif /* SYSTEM_MAXCONN */
849 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200850 else if (!strcmp(args[0], "maxsslconn")) {
851#ifdef USE_OPENSSL
852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857 global.maxsslconn = atol(args[1]);
858#else
Emeric Brun0914df82012-10-02 18:45:42 +0200859 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200862#endif
863 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200864 else if (!strcmp(args[0], "maxconnrate")) {
865 if (global.cps_lim != 0) {
866 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT;
868 goto out;
869 }
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.cps_lim = atol(args[1]);
876 }
William Lallemandd85f9172012-11-09 17:05:39 +0100877 else if (!strcmp(args[0], "maxcomprate")) {
878 if (*(args[1]) == 0) {
879 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 global.comp_rate_lim = atoi(args[1]) * 1024;
884 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100885 else if (!strcmp(args[0], "maxpipes")) {
886 if (global.maxpipes != 0) {
887 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200888 err_code |= ERR_ALERT;
889 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100890 }
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100895 }
896 global.maxpipes = atol(args[1]);
897 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100898 else if (!strcmp(args[0], "maxzlibmem")) {
899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
William Lallemande3a7d992012-11-20 11:25:20 +0100904 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100905 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100906 else if (!strcmp(args[0], "maxcompcpuusage")) {
907 if (*(args[1]) == 0) {
908 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911 }
912 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100913 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100914 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918}
919
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 else if (!strcmp(args[0], "ulimit-n")) {
921 if (global.rlimit_nofile != 0) {
922 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200923 err_code |= ERR_ALERT;
924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 }
926 if (*(args[1]) == 0) {
927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 global.rlimit_nofile = atol(args[1]);
932 }
933 else if (!strcmp(args[0], "chroot")) {
934 if (global.chroot != NULL) {
935 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT;
937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 }
939 if (*(args[1]) == 0) {
940 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 }
944 global.chroot = strdup(args[1]);
945 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200946 else if (!strcmp(args[0], "description")) {
947 int i, len=0;
948 char *d;
949
950 if (!*args[1]) {
951 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
952 file, linenum, args[0]);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
956
957 for(i=1; *args[i]; i++)
958 len += strlen(args[i])+1;
959
960 if (global.desc)
961 free(global.desc);
962
963 global.desc = d = (char *)calloc(1, len);
964
965 d += sprintf(d, "%s", args[1]);
966 for(i=2; *args[i]; i++)
967 d += sprintf(d, " %s", args[i]);
968 }
969 else if (!strcmp(args[0], "node")) {
970 int i;
971 char c;
972
973 for (i=0; args[1][i]; i++) {
974 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100975 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
976 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200977 break;
978 }
979
980 if (!i || args[1][i]) {
981 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
982 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
983 file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987
988 if (global.node)
989 free(global.node);
990
991 global.node = strdup(args[1]);
992 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 else if (!strcmp(args[0], "pidfile")) {
994 if (global.pidfile != NULL) {
995 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT;
997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 }
1004 global.pidfile = strdup(args[1]);
1005 }
Emeric Bruned760922010-10-22 17:59:25 +02001006 else if (!strcmp(args[0], "unix-bind")) {
1007 int cur_arg = 1;
1008 while (*(args[cur_arg])) {
1009 if (!strcmp(args[cur_arg], "prefix")) {
1010 if (global.unix_bind.prefix != NULL) {
1011 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1012 err_code |= ERR_ALERT;
1013 cur_arg += 2;
1014 continue;
1015 }
1016
1017 if (*(args[cur_arg+1]) == 0) {
1018 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
1021 }
1022 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1023 cur_arg += 2;
1024 continue;
1025 }
1026
1027 if (!strcmp(args[cur_arg], "mode")) {
1028
1029 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1030 cur_arg += 2;
1031 continue;
1032 }
1033
1034 if (!strcmp(args[cur_arg], "uid")) {
1035
1036 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1037 cur_arg += 2;
1038 continue;
1039 }
1040
1041 if (!strcmp(args[cur_arg], "gid")) {
1042
1043 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1044 cur_arg += 2;
1045 continue;
1046 }
1047
1048 if (!strcmp(args[cur_arg], "user")) {
1049 struct passwd *user;
1050
1051 user = getpwnam(args[cur_arg + 1]);
1052 if (!user) {
1053 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1054 file, linenum, args[0], args[cur_arg + 1 ]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058
1059 global.unix_bind.ux.uid = user->pw_uid;
1060 cur_arg += 2;
1061 continue;
1062 }
1063
1064 if (!strcmp(args[cur_arg], "group")) {
1065 struct group *group;
1066
1067 group = getgrnam(args[cur_arg + 1]);
1068 if (!group) {
1069 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1070 file, linenum, args[0], args[cur_arg + 1 ]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074
1075 global.unix_bind.ux.gid = group->gr_gid;
1076 cur_arg += 2;
1077 continue;
1078 }
1079
Willy Tarreaub48f9582011-09-05 01:17:06 +02001080 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001081 file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 }
William Lallemand0f99e342011-10-12 17:50:54 +02001086 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1087 /* delete previous herited or defined syslog servers */
1088 struct logsrv *back;
1089 struct logsrv *tmp;
1090
1091 if (*(args[1]) != 0) {
1092 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096
1097 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1098 LIST_DEL(&tmp->list);
1099 free(tmp);
1100 }
1101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001103 struct sockaddr_storage *sk;
1104 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001105 struct logsrv *logsrv;
1106
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 if (*(args[1]) == 0 || *(args[2]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001111 }
William Lallemand0f99e342011-10-12 17:50:54 +02001112
1113 logsrv = calloc(1, sizeof(struct logsrv));
1114
1115 logsrv->facility = get_log_facility(args[2]);
1116 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001119 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 }
1121
William Lallemand0f99e342011-10-12 17:50:54 +02001122 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001124 logsrv->level = get_log_level(args[3]);
1125 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001128 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 }
1130 }
1131
William Lallemand0f99e342011-10-12 17:50:54 +02001132 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001133 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001134 logsrv->minlvl = get_log_level(args[4]);
1135 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001136 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001137 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001138 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001139 }
1140 }
1141
Willy Tarreau902636f2013-03-10 19:44:48 +01001142 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001143 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001144 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001146 free(logsrv);
1147 goto out;
1148 }
1149 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001150
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001151 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001152 if (port1 != port2) {
1153 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1154 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001155 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001156 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001157 goto out;
1158 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001159
William Lallemand0f99e342011-10-12 17:50:54 +02001160 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001161 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001162 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164
William Lallemand0f99e342011-10-12 17:50:54 +02001165 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001166 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001167 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1168 char *name;
1169 int len;
1170
1171 if (global.log_send_hostname != NULL) {
1172 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1173 err_code |= ERR_ALERT;
1174 goto out;
1175 }
1176
1177 if (*(args[1]))
1178 name = args[1];
1179 else
1180 name = hostname;
1181
1182 len = strlen(name);
1183
1184 /* We'll add a space after the name to respect the log format */
1185 free(global.log_send_hostname);
1186 global.log_send_hostname = malloc(len + 2);
1187 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1188 }
Kevinm48936af2010-12-22 16:08:21 +00001189 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1190 if (*(args[1]) == 0) {
1191 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
1195 free(global.log_tag);
1196 global.log_tag = strdup(args[1]);
1197 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001198 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1199 if (global.spread_checks != 0) {
1200 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT;
1202 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001203 }
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001208 }
1209 global.spread_checks = atol(args[1]);
1210 if (global.spread_checks < 0 || global.spread_checks > 50) {
1211 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001215 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1216#ifdef USE_CPU_AFFINITY
1217 int cur_arg, i;
1218 unsigned int proc = 0;
1219 unsigned long cpus = 0;
1220
1221 if (strcmp(args[1], "all") == 0)
1222 proc = 0xFFFFFFFF;
1223 else if (strcmp(args[1], "odd") == 0)
1224 proc = 0x55555555;
1225 else if (strcmp(args[1], "even") == 0)
1226 proc = 0xAAAAAAAA;
1227 else {
1228 proc = atoi(args[1]);
1229 if (proc >= 1 && proc <= 32)
1230 proc = 1 << (proc - 1);
1231 }
1232
1233 if (!proc || !*args[2]) {
1234 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",
1235 file, linenum, args[0]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239
1240 cur_arg = 2;
1241 while (*args[cur_arg]) {
1242 unsigned int low, high;
1243
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001244 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001245 char *dash = strchr(args[cur_arg], '-');
1246
1247 low = high = str2uic(args[cur_arg]);
1248 if (dash)
1249 high = str2uic(dash + 1);
1250
1251 if (high < low) {
1252 unsigned int swap = low;
1253 low = high;
1254 high = swap;
1255 }
1256
1257 if (low < 0 || high >= sizeof(long) * 8) {
1258 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1259 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263
1264 while (low <= high)
1265 cpus |= 1UL << low++;
1266 }
1267 else {
1268 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1269 file, linenum, args[0], args[cur_arg]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272 }
1273 cur_arg++;
1274 }
1275 for (i = 0; i < 32; i++)
1276 if (proc & (1 << i))
1277 global.cpu_map[i] = cpus;
1278#else
1279 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282#endif
1283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001285 struct cfg_kw_list *kwl;
1286 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001287 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288
1289 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1290 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1291 if (kwl->kw[index].section != CFG_GLOBAL)
1292 continue;
1293 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001294 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001295 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001296 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001297 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001298 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001299 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001300 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001301 err_code |= ERR_WARN;
1302 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001303 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001304 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001305 }
1306 }
1307 }
1308
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001312
Willy Tarreau058e9072009-07-20 09:30:05 +02001313 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001314 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316}
1317
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001318void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001320 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001321 defproxy.mode = PR_MODE_TCP;
1322 defproxy.state = PR_STNEW;
1323 defproxy.maxconn = cfg_maxpconn;
1324 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001325
Simon Horman66183002013-02-23 10:16:43 +09001326 defproxy.defsrv.check.inter = DEF_CHKINTR;
1327 defproxy.defsrv.check.fastinter = 0;
1328 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001329 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1330 defproxy.defsrv.agent.fastinter = 0;
1331 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001332 defproxy.defsrv.check.rise = DEF_RISETIME;
1333 defproxy.defsrv.check.fall = DEF_FALLTIME;
1334 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1335 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001336 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001337 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001338 defproxy.defsrv.maxqueue = 0;
1339 defproxy.defsrv.minconn = 0;
1340 defproxy.defsrv.maxconn = 0;
1341 defproxy.defsrv.slowstart = 0;
1342 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1343 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1344 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345}
1346
Willy Tarreauade5ec42010-01-28 19:33:49 +01001347
1348static int create_cond_regex_rule(const char *file, int line,
1349 struct proxy *px, int dir, int action, int flags,
1350 const char *cmd, const char *reg, const char *repl,
1351 const char **cond_start)
1352{
1353 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001354 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001355 const char *err;
1356 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001357 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001358
1359 if (px == &defproxy) {
1360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto err;
1363 }
1364
1365 if (*reg == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto err;
1369 }
1370
1371 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1372 err_code |= ERR_WARN;
1373
Willy Tarreau5321c422010-01-28 20:35:13 +01001374 if (cond_start &&
1375 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001376 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1377 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1378 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382 }
1383 else if (cond_start && **cond_start) {
1384 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1385 file, line, cmd, *cond_start);
1386 err_code |= ERR_ALERT | ERR_FATAL;
1387 goto err;
1388 }
1389
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001390 err_code |= warnif_cond_conflicts(cond,
1391 (dir == SMP_OPT_DIR_REQ) ?
1392 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1393 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1394 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001395
Willy Tarreauade5ec42010-01-28 19:33:49 +01001396 preg = calloc(1, sizeof(regex_t));
1397 if (!preg) {
1398 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1399 err_code = ERR_ALERT | ERR_FATAL;
1400 goto err;
1401 }
1402
1403 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1404 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1405 err_code = ERR_ALERT | ERR_FATAL;
1406 goto err;
1407 }
1408
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001409 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001410 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001411 if (repl && err) {
1412 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1413 file, line, cmd, *err);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto err;
1416 }
1417
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001418 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001419 err_code |= ERR_WARN;
1420
Willy Tarreauf4068b62012-05-08 17:37:49 +02001421 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001422 return err_code;
1423 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001424 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001425 free(preg);
1426 return err_code;
1427}
1428
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001430 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001431 * Returns the error code, 0 if OK, or any combination of :
1432 * - ERR_ABORT: must abort ASAP
1433 * - ERR_FATAL: we can continue parsing but not start the service
1434 * - ERR_WARN: a warning has been emitted
1435 * - ERR_ALERT: an alert has been emitted
1436 * Only the two first ones can stop processing, the two others are just
1437 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001439int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1440{
1441 static struct peers *curpeers = NULL;
1442 struct peer *newpeer = NULL;
1443 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001444 struct bind_conf *bind_conf;
1445 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001446 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001447 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001450 if (!*args[1]) {
1451 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1452 err_code |= ERR_ALERT | ERR_FATAL;
1453 goto out;
1454 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001455
1456 err = invalid_char(args[1]);
1457 if (err) {
1458 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1459 file, linenum, *err, args[0], args[1]);
1460 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001461 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001462 }
1463
1464 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1465 /*
1466 * If there are two proxies with the same name only following
1467 * combinations are allowed:
1468 */
1469 if (strcmp(curpeers->id, args[1]) == 0) {
1470 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1471 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1472 err_code |= ERR_WARN;
1473 }
1474 }
1475
1476 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1478 err_code |= ERR_ALERT | ERR_ABORT;
1479 goto out;
1480 }
1481
1482 curpeers->next = peers;
1483 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001484 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001485 curpeers->conf.line = linenum;
1486 curpeers->last_change = now.tv_sec;
1487 curpeers->id = strdup(args[1]);
1488 }
1489 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001490 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001491 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001492 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001493
1494 if (!*args[2]) {
1495 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1496 file, linenum, args[0]);
1497 err_code |= ERR_ALERT | ERR_FATAL;
1498 goto out;
1499 }
1500
1501 err = invalid_char(args[1]);
1502 if (err) {
1503 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1504 file, linenum, *err, args[1]);
1505 err_code |= ERR_ALERT | ERR_FATAL;
1506 goto out;
1507 }
1508
1509 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1510 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1511 err_code |= ERR_ALERT | ERR_ABORT;
1512 goto out;
1513 }
1514
1515 /* the peers are linked backwards first */
1516 curpeers->count++;
1517 newpeer->next = curpeers->remote;
1518 curpeers->remote = newpeer;
1519 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001520 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001521 newpeer->conf.line = linenum;
1522
1523 newpeer->last_change = now.tv_sec;
1524 newpeer->id = strdup(args[1]);
1525
Willy Tarreau902636f2013-03-10 19:44:48 +01001526 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001527 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001528 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001531 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001532
1533 proto = protocol_by_family(sk->ss_family);
1534 if (!proto || !proto->connect) {
1535 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1536 file, linenum, args[0], args[1]);
1537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001540
1541 if (port1 != port2) {
1542 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1543 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
1547
Willy Tarreau2aa38802013-02-20 19:20:59 +01001548 if (!port1) {
1549 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1550 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001551 err_code |= ERR_ALERT | ERR_FATAL;
1552 goto out;
1553 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001554
Emeric Brun32da3c42010-09-23 18:39:19 +02001555 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001556 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001557 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001558 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001559
Emeric Brun32da3c42010-09-23 18:39:19 +02001560 if (strcmp(newpeer->id, localpeer) == 0) {
1561 /* Current is local peer, it define a frontend */
1562 newpeer->local = 1;
1563
1564 if (!curpeers->peers_fe) {
1565 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1566 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1567 err_code |= ERR_ALERT | ERR_ABORT;
1568 goto out;
1569 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001570
Willy Tarreau237250c2011-07-29 01:49:03 +02001571 init_new_proxy(curpeers->peers_fe);
1572 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001573
1574 curpeers->peers_fe->last_change = now.tv_sec;
1575 curpeers->peers_fe->id = strdup(args[1]);
1576 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001577 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001578 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1579 curpeers->peers_fe->timeout.connect = 5000;
1580 curpeers->peers_fe->accept = peer_accept;
1581 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001582 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1583 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001584
1585 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1586
Willy Tarreau902636f2013-03-10 19:44:48 +01001587 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1588 if (errmsg && *errmsg) {
1589 indent_msg(&errmsg, 2);
1590 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001591 }
1592 else
1593 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1594 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001595 err_code |= ERR_FATAL;
1596 goto out;
1597 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001598
1599 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1600 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1601 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1602 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1603 l->accept = session_accept;
1604 l->handler = process_session;
1605 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1606 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1607 global.maxsock += l->maxconn;
1608 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001609 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001610 else {
1611 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1612 file, linenum, args[0], args[1],
1613 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1614 err_code |= ERR_FATAL;
1615 goto out;
1616 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001617 }
1618 } /* neither "peer" nor "peers" */
1619 else if (*args[0] != 0) {
1620 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624
1625out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001626 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001627 return err_code;
1628}
1629
Simon Horman69d29f92013-02-23 15:14:19 +09001630static int init_check(struct check *check, int type, const char * file, int linenum)
1631{
1632 check->type = type;
1633
1634 /* Allocate buffer for requests... */
1635 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1636 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1637 return ERR_ALERT | ERR_ABORT;
1638 }
1639 check->bi->size = global.tune.chksize;
1640
1641 /* Allocate buffer for responses... */
1642 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1643 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1644 return ERR_ALERT | ERR_ABORT;
1645 }
1646 check->bo->size = global.tune.chksize;
1647
1648 /* Allocate buffer for partial results... */
1649 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1650 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1651 return ERR_ALERT | ERR_ABORT;
1652 }
1653
1654 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1655
1656 return 0;
1657}
Emeric Brun32da3c42010-09-23 18:39:19 +02001658
Willy Tarreau3842f002009-06-14 11:39:52 +02001659int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660{
1661 static struct proxy *curproxy = NULL;
1662 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001663 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001664 int rc;
1665 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001666 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001667 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001668 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001669 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001670 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671
Willy Tarreau977b8e42006-12-29 14:19:17 +01001672 if (!strcmp(args[0], "listen"))
1673 rc = PR_CAP_LISTEN;
1674 else if (!strcmp(args[0], "frontend"))
1675 rc = PR_CAP_FE | PR_CAP_RS;
1676 else if (!strcmp(args[0], "backend"))
1677 rc = PR_CAP_BE | PR_CAP_RS;
1678 else if (!strcmp(args[0], "ruleset"))
1679 rc = PR_CAP_RS;
1680 else
1681 rc = PR_CAP_NONE;
1682
1683 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 if (!*args[1]) {
1685 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1686 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1687 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_ABORT;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001691
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001692 err = invalid_char(args[1]);
1693 if (err) {
1694 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1695 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001696 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001697 }
1698
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001699 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1700 /*
1701 * If there are two proxies with the same name only following
1702 * combinations are allowed:
1703 *
1704 * listen backend frontend ruleset
1705 * listen - - - -
1706 * backend - - OK -
1707 * frontend - OK - -
1708 * ruleset - - - -
1709 */
1710
1711 if (!strcmp(curproxy->id, args[1]) &&
1712 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1713 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001714 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1715 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1716 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001717 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001718 }
1719 }
1720
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1722 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001723 err_code |= ERR_ALERT | ERR_ABORT;
1724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001726
Willy Tarreau97cb7802010-01-03 20:23:58 +01001727 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->next = proxy;
1729 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001730 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1731 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001732 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001734 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735
1736 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001737 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001738 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001739
Willy Tarreau4348fad2012-09-20 16:48:07 +02001740 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1741
Willy Tarreau902636f2013-03-10 19:44:48 +01001742 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1743 if (errmsg && *errmsg) {
1744 indent_msg(&errmsg, 2);
1745 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001746 }
1747 else
1748 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1749 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_FATAL;
1751 goto out;
1752 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001753
Willy Tarreau4348fad2012-09-20 16:48:07 +02001754 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001755 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 }
1758
1759 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001760 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001761 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001762
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001765 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001766 curproxy->no_options = defproxy.no_options;
1767 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001768 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001769 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001770 curproxy->except_net = defproxy.except_net;
1771 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001772 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001773 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001775 if (defproxy.fwdfor_hdr_len) {
1776 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1777 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1778 }
1779
Willy Tarreaub86db342009-11-30 11:50:16 +01001780 if (defproxy.orgto_hdr_len) {
1781 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1782 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1783 }
1784
Mark Lamourinec2247f02012-01-04 13:02:01 -05001785 if (defproxy.server_id_hdr_len) {
1786 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1787 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1788 }
1789
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 if (curproxy->cap & PR_CAP_FE) {
1791 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001792 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001793 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794
1795 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001796 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1797 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001798
1799 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 if (curproxy->cap & PR_CAP_BE) {
1803 curproxy->fullconn = defproxy.fullconn;
1804 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001806 if (defproxy.check_req) {
1807 curproxy->check_req = calloc(1, defproxy.check_len);
1808 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1809 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001812 if (defproxy.expect_str) {
1813 curproxy->expect_str = strdup(defproxy.expect_str);
1814 if (defproxy.expect_regex) {
1815 /* note: this regex is known to be valid */
1816 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1817 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1818 }
1819 }
1820
Willy Tarreau67402132012-05-31 20:40:20 +02001821 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 if (defproxy.cookie_name)
1823 curproxy->cookie_name = strdup(defproxy.cookie_name);
1824 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001825 if (defproxy.cookie_domain)
1826 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001827
Willy Tarreau31936852010-10-06 16:59:56 +02001828 if (defproxy.cookie_maxidle)
1829 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1830
1831 if (defproxy.cookie_maxlife)
1832 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1833
Emeric Brun647caf12009-06-30 17:57:00 +02001834 if (defproxy.rdp_cookie_name)
1835 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1836 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1837
Willy Tarreau01732802007-11-01 22:48:15 +01001838 if (defproxy.url_param_name)
1839 curproxy->url_param_name = strdup(defproxy.url_param_name);
1840 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001841
Benoitaffb4812009-03-25 13:02:10 +01001842 if (defproxy.hh_name)
1843 curproxy->hh_name = strdup(defproxy.hh_name);
1844 curproxy->hh_len = defproxy.hh_len;
1845 curproxy->hh_match_domain = defproxy.hh_match_domain;
1846
Willy Tarreauef9a3602012-12-08 22:29:20 +01001847 if (defproxy.conn_src.iface_name)
1848 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1849 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001850 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001851#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001852 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001853#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001856 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857 if (defproxy.capture_name)
1858 curproxy->capture_name = strdup(defproxy.capture_name);
1859 curproxy->capture_namelen = defproxy.capture_namelen;
1860 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862
Willy Tarreau977b8e42006-12-29 14:19:17 +01001863 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001864 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001865 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001866 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001867 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001868 curproxy->uri_auth = defproxy.uri_auth;
1869 curproxy->mon_net = defproxy.mon_net;
1870 curproxy->mon_mask = defproxy.mon_mask;
1871 if (defproxy.monitor_uri)
1872 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1873 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001874 if (defproxy.defbe.name)
1875 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001876
1877 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001878 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1879 if (curproxy->conf.logformat_string &&
1880 curproxy->conf.logformat_string != default_http_log_format &&
1881 curproxy->conf.logformat_string != default_tcp_log_format &&
1882 curproxy->conf.logformat_string != clf_http_log_format)
1883 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1884
1885 if (defproxy.conf.lfs_file) {
1886 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1887 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001889 }
1890
1891 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001892 curproxy->timeout.connect = defproxy.timeout.connect;
1893 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001894 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001895 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001896 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001897 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001898 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001899 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001900 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901 }
1902
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001904
1905 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001906 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001907 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001908 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001909 LIST_INIT(&node->list);
1910 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1911 }
1912
Willy Tarreau62a61232013-04-12 18:13:46 +02001913 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1914 if (curproxy->conf.uniqueid_format_string)
1915 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1916
1917 if (defproxy.conf.uif_file) {
1918 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1919 curproxy->conf.uif_line = defproxy.conf.uif_line;
1920 }
William Lallemanda73203e2012-03-12 12:48:57 +01001921
1922 /* copy default header unique id */
1923 if (defproxy.header_unique_id)
1924 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1925
William Lallemand82fe75c2012-10-23 10:25:10 +02001926 /* default compression options */
1927 if (defproxy.comp != NULL) {
1928 curproxy->comp = calloc(1, sizeof(struct comp));
1929 curproxy->comp->algos = defproxy.comp->algos;
1930 curproxy->comp->types = defproxy.comp->types;
1931 }
1932
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001934 curproxy->conf.used_listener_id = EB_ROOT;
1935 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001936
Willy Tarreau93893792009-07-23 13:19:11 +02001937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 }
1939 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1940 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001941 /* FIXME-20070101: we should do this too at the end of the
1942 * config parsing to free all default values.
1943 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001944 free(defproxy.check_req);
1945 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001946 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001947 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001948 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001949 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001950 free(defproxy.capture_name);
1951 free(defproxy.monitor_uri);
1952 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001953 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001954 free(defproxy.fwdfor_hdr_name);
1955 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001956 free(defproxy.orgto_hdr_name);
1957 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001958 free(defproxy.server_id_hdr_name);
1959 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001960 free(defproxy.expect_str);
1961 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001962
Willy Tarreau62a61232013-04-12 18:13:46 +02001963 if (defproxy.conf.logformat_string != default_http_log_format &&
1964 defproxy.conf.logformat_string != default_tcp_log_format &&
1965 defproxy.conf.logformat_string != clf_http_log_format)
1966 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001967
Willy Tarreau62a61232013-04-12 18:13:46 +02001968 free(defproxy.conf.uniqueid_format_string);
1969 free(defproxy.conf.lfs_file);
1970 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001971
Willy Tarreaua534fea2008-08-03 12:19:50 +02001972 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001973 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001974
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 /* we cannot free uri_auth because it might already be used */
1976 init_default_instance();
1977 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001978 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1979 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001980 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 }
1983 else if (curproxy == NULL) {
1984 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001988
1989 /* update the current file and line being parsed */
1990 curproxy->conf.args.file = curproxy->conf.file;
1991 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992
1993 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001995 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001996 int cur_arg;
1997
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 if (curproxy == &defproxy) {
1999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002003 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002004 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005
Willy Tarreau24709282013-03-10 21:32:12 +01002006 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002007 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002012
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002013 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002014
2015 /* use default settings for unix sockets */
2016 bind_conf->ux.uid = global.unix_bind.ux.uid;
2017 bind_conf->ux.gid = global.unix_bind.ux.gid;
2018 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002019
2020 /* NOTE: the following line might create several listeners if there
2021 * are comma-separated IPs or port ranges. So all further processing
2022 * will have to be applied to all listeners created after last_listen.
2023 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002024 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2025 if (errmsg && *errmsg) {
2026 indent_msg(&errmsg, 2);
2027 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002028 }
2029 else
2030 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2031 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
2034 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002035
Willy Tarreau4348fad2012-09-20 16:48:07 +02002036 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2037 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002038 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002039 }
2040
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002041 cur_arg = 2;
2042 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002043 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002044 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002045 char *err;
2046
Willy Tarreau26982662012-09-12 23:17:10 +02002047 kw = bind_find_kw(args[cur_arg]);
2048 if (kw) {
2049 char *err = NULL;
2050 int code;
2051
2052 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002053 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2054 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002055 cur_arg += 1 + kw->skip ;
2056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
2058 }
2059
Willy Tarreau4348fad2012-09-20 16:48:07 +02002060 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002061 err_code |= code;
2062
2063 if (code) {
2064 if (err && *err) {
2065 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002066 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002067 }
2068 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002069 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2070 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002071 if (code & ERR_FATAL) {
2072 free(err);
2073 cur_arg += 1 + kw->skip;
2074 goto out;
2075 }
2076 }
2077 free(err);
2078 cur_arg += 1 + kw->skip;
2079 continue;
2080 }
2081
Willy Tarreau8638f482012-09-18 18:01:17 +02002082 err = NULL;
2083 if (!bind_dumped) {
2084 bind_dump_kws(&err);
2085 indent_msg(&err, 4);
2086 bind_dumped = 1;
2087 }
2088
2089 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2090 file, linenum, args[0], args[1], args[cur_arg],
2091 err ? " Registered keywords :" : "", err ? err : "");
2092 free(err);
2093
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002096 }
Willy Tarreau93893792009-07-23 13:19:11 +02002097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 }
2099 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2100 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2101 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002106 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 /* flush useless bits */
2110 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002113 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002114 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002116
Willy Tarreau1c47f852006-07-09 08:22:27 +02002117 if (!*args[1]) {
2118 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002122 }
2123
Willy Tarreaua534fea2008-08-03 12:19:50 +02002124 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002125 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002126 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002127 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002128 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2129
Willy Tarreau93893792009-07-23 13:19:11 +02002130 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2133 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2134 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2135 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2136 else {
2137 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002138 err_code |= ERR_ALERT | ERR_FATAL;
2139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 }
2141 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002142 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002143 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002144
2145 if (curproxy == &defproxy) {
2146 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2147 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002150 }
2151
2152 if (!*args[1]) {
2153 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2154 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002157 }
2158
2159 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002160 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002161
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002162 if (curproxy->uuid <= 0) {
2163 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002164 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002167 }
2168
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002169 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2170 if (node) {
2171 struct proxy *target = container_of(node, struct proxy, conf.id);
2172 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2173 file, linenum, proxy_type_str(curproxy), curproxy->id,
2174 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002179 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002180 else if (!strcmp(args[0], "description")) {
2181 int i, len=0;
2182 char *d;
2183
Cyril Bonté99ed3272010-01-24 23:29:44 +01002184 if (curproxy == &defproxy) {
2185 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2186 file, linenum, args[0]);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002191 if (!*args[1]) {
2192 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2193 file, linenum, args[0]);
2194 return -1;
2195 }
2196
2197 for(i=1; *args[i]; i++)
2198 len += strlen(args[i])+1;
2199
2200 d = (char *)calloc(1, len);
2201 curproxy->desc = d;
2202
2203 d += sprintf(d, "%s", args[1]);
2204 for(i=2; *args[i]; i++)
2205 d += sprintf(d, " %s", args[i]);
2206
2207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2209 curproxy->state = PR_STSTOPPED;
2210 }
2211 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2212 curproxy->state = PR_STNEW;
2213 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002214 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2215 int cur_arg = 1;
2216 unsigned int set = 0;
2217
2218 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002219 unsigned int low, high;
2220
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002221 if (strcmp(args[cur_arg], "all") == 0) {
2222 set = 0;
2223 break;
2224 }
2225 else if (strcmp(args[cur_arg], "odd") == 0) {
2226 set |= 0x55555555;
2227 }
2228 else if (strcmp(args[cur_arg], "even") == 0) {
2229 set |= 0xAAAAAAAA;
2230 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002231 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002232 char *dash = strchr(args[cur_arg], '-');
2233
2234 low = high = str2uic(args[cur_arg]);
2235 if (dash)
2236 high = str2uic(dash + 1);
2237
2238 if (high < low) {
2239 unsigned int swap = low;
2240 low = high;
2241 high = swap;
2242 }
2243
2244 if (low < 1 || high > 32) {
2245 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002249 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002250
2251 if (high > global.nbproc) {
2252 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2253 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002255 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002256 while (low <= high)
2257 set |= 1 << (low++ - 1);
2258 }
2259 else {
2260 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2261 file, linenum, args[0]);
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002264 }
2265 cur_arg++;
2266 }
2267 curproxy->bind_proc = set;
2268 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002269 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002270 if (curproxy == &defproxy) {
2271 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002274 }
2275
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002276 err = invalid_char(args[1]);
2277 if (err) {
2278 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2279 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002281 }
2282
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002283 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002284 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2285 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002288 }
2289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2291 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 if (*(args[1]) == 0) {
2297 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002302
Willy Tarreau67402132012-05-31 20:40:20 +02002303 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002304 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002305 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002306 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307 curproxy->cookie_name = strdup(args[1]);
2308 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002309
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 cur_arg = 2;
2311 while (*(args[cur_arg])) {
2312 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002313 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 }
2315 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002316 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 }
2318 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002319 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 }
2321 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002322 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 }
2324 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002325 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002327 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002328 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002331 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002333 else if (!strcmp(args[cur_arg], "httponly")) {
2334 curproxy->ck_opts |= PR_CK_HTTPONLY;
2335 }
2336 else if (!strcmp(args[cur_arg], "secure")) {
2337 curproxy->ck_opts |= PR_CK_SECURE;
2338 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002339 else if (!strcmp(args[cur_arg], "domain")) {
2340 if (!*args[cur_arg + 1]) {
2341 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2342 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002345 }
2346
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002347 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002348 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002349 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2350 " dots nor does not start with a dot."
2351 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002352 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002353 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002354 }
2355
2356 err = invalid_domainchar(args[cur_arg + 1]);
2357 if (err) {
2358 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2359 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002362 }
2363
Willy Tarreau68a897b2009-12-03 23:28:34 +01002364 if (!curproxy->cookie_domain) {
2365 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2366 } else {
2367 /* one domain was already specified, add another one by
2368 * building the string which will be returned along with
2369 * the cookie.
2370 */
2371 char *new_ptr;
2372 int new_len = strlen(curproxy->cookie_domain) +
2373 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2374 new_ptr = malloc(new_len);
2375 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2376 free(curproxy->cookie_domain);
2377 curproxy->cookie_domain = new_ptr;
2378 }
Willy Tarreau31936852010-10-06 16:59:56 +02002379 cur_arg++;
2380 }
2381 else if (!strcmp(args[cur_arg], "maxidle")) {
2382 unsigned int maxidle;
2383 const char *res;
2384
2385 if (!*args[cur_arg + 1]) {
2386 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2387 file, linenum, args[cur_arg]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
2392 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2393 if (res) {
2394 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2395 file, linenum, *res, args[cur_arg]);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
2398 }
2399 curproxy->cookie_maxidle = maxidle;
2400 cur_arg++;
2401 }
2402 else if (!strcmp(args[cur_arg], "maxlife")) {
2403 unsigned int maxlife;
2404 const char *res;
2405
2406 if (!*args[cur_arg + 1]) {
2407 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2408 file, linenum, args[cur_arg]);
2409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
2411 }
2412
2413 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2414 if (res) {
2415 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2416 file, linenum, *res, args[cur_arg]);
2417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
2419 }
2420 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002421 cur_arg++;
2422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002424 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 +02002425 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
2429 cur_arg++;
2430 }
Willy Tarreau67402132012-05-31 20:40:20 +02002431 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2433 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
2436
Willy Tarreau67402132012-05-31 20:40:20 +02002437 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2439 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002442
Willy Tarreau67402132012-05-31 20:40:20 +02002443 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002444 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2445 file, linenum);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002449 else if (!strcmp(args[0], "persist")) { /* persist */
2450 if (*(args[1]) == 0) {
2451 Alert("parsing [%s:%d] : missing persist method.\n",
2452 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002455 }
2456
2457 if (!strncmp(args[1], "rdp-cookie", 10)) {
2458 curproxy->options2 |= PR_O2_RDPC_PRST;
2459
Emeric Brunb982a3d2010-01-04 15:45:53 +01002460 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002461 const char *beg, *end;
2462
2463 beg = args[1] + 11;
2464 end = strchr(beg, ')');
2465
2466 if (!end || end == beg) {
2467 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2468 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002471 }
2472
2473 free(curproxy->rdp_cookie_name);
2474 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2475 curproxy->rdp_cookie_len = end-beg;
2476 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002477 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002478 free(curproxy->rdp_cookie_name);
2479 curproxy->rdp_cookie_name = strdup("msts");
2480 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2481 }
2482 else { /* syntax */
2483 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2484 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002487 }
2488 }
2489 else {
2490 Alert("parsing [%s:%d] : unknown persist method.\n",
2491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002494 }
2495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002497 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002499 if (curproxy == &defproxy) {
2500 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
2504
Willy Tarreau977b8e42006-12-29 14:19:17 +01002505 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002507
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002509 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 }
2514 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002515 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 curproxy->appsession_name = strdup(args[1]);
2517 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2518 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002519 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2520 if (err) {
2521 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2522 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002525 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002526 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002527
Willy Tarreau51041c72007-09-09 21:56:53 +02002528 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2529 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_ABORT;
2531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002533
2534 cur_arg = 6;
2535 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002536 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2537 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002538 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002539 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002540 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002541 } else if (!strcmp(args[cur_arg], "prefix")) {
2542 curproxy->options2 |= PR_O2_AS_PFX;
2543 } else if (!strcmp(args[cur_arg], "mode")) {
2544 if (!*args[cur_arg + 1]) {
2545 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2546 file, linenum, args[0], args[cur_arg]);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
2549 }
2550
2551 cur_arg++;
2552 if (!strcmp(args[cur_arg], "query-string")) {
2553 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2554 curproxy->options2 |= PR_O2_AS_M_QS;
2555 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2556 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2557 curproxy->options2 |= PR_O2_AS_M_PP;
2558 } else {
2559 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
2562 }
2563 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002564 cur_arg++;
2565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 } /* Url App Session */
2567 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002568 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002572 if (curproxy == &defproxy) {
2573 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 if (*(args[4]) == 0) {
2579 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2580 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002584 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 curproxy->capture_name = strdup(args[2]);
2586 curproxy->capture_namelen = strlen(curproxy->capture_name);
2587 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 curproxy->to_log |= LW_COOKIE;
2589 }
2590 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2591 struct cap_hdr *hdr;
2592
2593 if (curproxy == &defproxy) {
2594 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 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
2598
2599 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2600 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2601 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 }
2605
2606 hdr = calloc(sizeof(struct cap_hdr), 1);
2607 hdr->next = curproxy->req_cap;
2608 hdr->name = strdup(args[3]);
2609 hdr->namelen = strlen(args[3]);
2610 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002611 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 hdr->index = curproxy->nb_req_cap++;
2613 curproxy->req_cap = hdr;
2614 curproxy->to_log |= LW_REQHDR;
2615 }
2616 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2617 struct cap_hdr *hdr;
2618
2619 if (curproxy == &defproxy) {
2620 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 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 }
2624
2625 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2626 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2627 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 }
2631 hdr = calloc(sizeof(struct cap_hdr), 1);
2632 hdr->next = curproxy->rsp_cap;
2633 hdr->name = strdup(args[3]);
2634 hdr->namelen = strlen(args[3]);
2635 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002636 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 hdr->index = curproxy->nb_rsp_cap++;
2638 curproxy->rsp_cap = hdr;
2639 curproxy->to_log |= LW_RSPHDR;
2640 }
2641 else {
2642 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2643 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
2647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 if (*(args[1]) == 0) {
2653 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2654 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 }
2658 curproxy->conn_retries = atol(args[1]);
2659 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002660 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002661 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002662
2663 if (curproxy == &defproxy) {
2664 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
2667 }
2668
Willy Tarreau20b0de52012-12-24 15:45:22 +01002669 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2670 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2671 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2672 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002673 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002674 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2675 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 +01002676 file, linenum, args[0]);
2677 err_code |= ERR_WARN;
2678 }
2679
Willy Tarreauff011f22011-01-06 17:51:27 +01002680 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002681
Willy Tarreauff011f22011-01-06 17:51:27 +01002682 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002683 err_code |= ERR_ALERT | ERR_ABORT;
2684 goto out;
2685 }
2686
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002687 err_code |= warnif_cond_conflicts(rule->cond,
2688 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2689 file, linenum);
2690
Willy Tarreauff011f22011-01-06 17:51:27 +01002691 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002692 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002693 else if (!strcmp(args[0], "http-response")) { /* response access control */
2694 struct http_res_rule *rule;
2695
2696 if (curproxy == &defproxy) {
2697 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
2700 }
2701
2702 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2703 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2704 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2705 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2706 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2707 file, linenum, args[0]);
2708 err_code |= ERR_WARN;
2709 }
2710
2711 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2712
2713 if (!rule) {
2714 err_code |= ERR_ALERT | ERR_ABORT;
2715 goto out;
2716 }
2717
2718 err_code |= warnif_cond_conflicts(rule->cond,
2719 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2720 file, linenum);
2721
2722 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2723 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002724 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2725 /* set the header name and length into the proxy structure */
2726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2727 err_code |= ERR_WARN;
2728
2729 if (!*args[1]) {
2730 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2731 file, linenum, args[0]);
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735
2736 /* set the desired header name */
2737 free(curproxy->server_id_hdr_name);
2738 curproxy->server_id_hdr_name = strdup(args[1]);
2739 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2740 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002741 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002742 if (curproxy == &defproxy) {
2743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002746 }
2747
Willy Tarreauef6494c2010-01-28 17:12:36 +01002748 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002749 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2750 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002753 }
2754
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002755 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2756 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2757 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002760 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002761
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002762 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002763 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002764 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002765 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002766 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002767
Cyril Bonté99ed3272010-01-24 23:29:44 +01002768 if (curproxy == &defproxy) {
2769 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
2772 }
2773
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002774 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002775 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2776 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002779 }
2780
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002781 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002782 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002783 err_code |= warnif_cond_conflicts(rule->cond,
2784 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2785 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002786 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002787 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002788 struct switching_rule *rule;
2789
Willy Tarreaub099aca2008-10-12 17:26:37 +02002790 if (curproxy == &defproxy) {
2791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002794 }
2795
Willy Tarreau55ea7572007-06-17 19:56:27 +02002796 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002798
2799 if (*(args[1]) == 0) {
2800 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002803 }
2804
Willy Tarreauef6494c2010-01-28 17:12:36 +01002805 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002806 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2807 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002810 }
2811
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002812 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2813 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2814 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002817 }
2818
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002819 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002820
Willy Tarreau55ea7572007-06-17 19:56:27 +02002821 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2822 rule->cond = cond;
2823 rule->be.name = strdup(args[1]);
2824 LIST_INIT(&rule->list);
2825 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2826 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002827 else if (strcmp(args[0], "use-server") == 0) {
2828 struct server_rule *rule;
2829
2830 if (curproxy == &defproxy) {
2831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
2834 }
2835
2836 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2837 err_code |= ERR_WARN;
2838
2839 if (*(args[1]) == 0) {
2840 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844
2845 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2846 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2847 file, linenum, args[0]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002852 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2853 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2854 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002859 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002860
2861 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2862 rule->cond = cond;
2863 rule->srv.name = strdup(args[1]);
2864 LIST_INIT(&rule->list);
2865 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2866 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2867 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002868 else if ((!strcmp(args[0], "force-persist")) ||
2869 (!strcmp(args[0], "ignore-persist"))) {
2870 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002871
2872 if (curproxy == &defproxy) {
2873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877
2878 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2879 err_code |= ERR_WARN;
2880
Willy Tarreauef6494c2010-01-28 17:12:36 +01002881 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002882 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2883 file, linenum, args[0]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002888 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2889 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2890 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
2893 }
2894
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002895 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2896 * where force-persist is applied.
2897 */
2898 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002899
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002900 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002901 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002902 if (!strcmp(args[0], "force-persist")) {
2903 rule->type = PERSIST_TYPE_FORCE;
2904 } else {
2905 rule->type = PERSIST_TYPE_IGNORE;
2906 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002907 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002908 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002909 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002910 else if (!strcmp(args[0], "stick-table")) {
2911 int myidx = 1;
2912
Emeric Brun32da3c42010-09-23 18:39:19 +02002913 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002914 curproxy->table.type = (unsigned int)-1;
2915 while (*args[myidx]) {
2916 const char *err;
2917
2918 if (strcmp(args[myidx], "size") == 0) {
2919 myidx++;
2920 if (!*(args[myidx])) {
2921 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2922 file, linenum, args[myidx-1]);
2923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
2925 }
2926 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2927 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2928 file, linenum, *err, args[myidx-1]);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002932 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002933 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002934 else if (strcmp(args[myidx], "peers") == 0) {
2935 myidx++;
Godbach50523162013-12-11 19:48:57 +08002936 if (!*(args[myidx])) {
2937 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2938 file, linenum, args[myidx-1]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002942 curproxy->table.peers.name = strdup(args[myidx++]);
2943 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002944 else if (strcmp(args[myidx], "expire") == 0) {
2945 myidx++;
2946 if (!*(args[myidx])) {
2947 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2948 file, linenum, args[myidx-1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2953 if (err) {
2954 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2955 file, linenum, *err, args[myidx-1]);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002960 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 }
2962 else if (strcmp(args[myidx], "nopurge") == 0) {
2963 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002964 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002965 }
2966 else if (strcmp(args[myidx], "type") == 0) {
2967 myidx++;
2968 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2969 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2970 file, linenum, args[myidx]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002974 /* myidx already points to next arg */
2975 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002976 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002977 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002978 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002979
2980 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002981 nw = args[myidx];
2982 while (*nw) {
2983 /* the "store" keyword supports a comma-separated list */
2984 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002985 sa = NULL; /* store arg */
2986 while (*nw && *nw != ',') {
2987 if (*nw == '(') {
2988 *nw = 0;
2989 sa = ++nw;
2990 while (*nw != ')') {
2991 if (!*nw) {
2992 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2993 file, linenum, args[0], cw);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997 nw++;
2998 }
2999 *nw = '\0';
3000 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003001 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003002 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003003 if (*nw)
3004 *nw++ = '\0';
3005 type = stktable_get_data_type(cw);
3006 if (type < 0) {
3007 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3008 file, linenum, args[0], cw);
3009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
3011 }
Willy Tarreauac782882010-06-20 10:41:54 +02003012
3013 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3014 switch (err) {
3015 case PE_NONE: break;
3016 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003017 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3018 file, linenum, args[0], cw);
3019 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003020 break;
3021
3022 case PE_ARG_MISSING:
3023 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3024 file, linenum, args[0], cw);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027
3028 case PE_ARG_NOT_USED:
3029 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3030 file, linenum, args[0], cw);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033
3034 default:
3035 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3036 file, linenum, args[0], cw);
3037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003039 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003040 }
3041 myidx++;
3042 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003043 else {
3044 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3045 file, linenum, args[myidx]);
3046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003049 }
3050
3051 if (!curproxy->table.size) {
3052 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3053 file, linenum);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
3057
3058 if (curproxy->table.type == (unsigned int)-1) {
3059 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3060 file, linenum);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
3063 }
3064 }
3065 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003067 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 int myidx = 0;
3069 const char *name = NULL;
3070 int flags;
3071
3072 if (curproxy == &defproxy) {
3073 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
3077
3078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3079 err_code |= ERR_WARN;
3080 goto out;
3081 }
3082
3083 myidx++;
3084 if ((strcmp(args[myidx], "store") == 0) ||
3085 (strcmp(args[myidx], "store-request") == 0)) {
3086 myidx++;
3087 flags = STK_IS_STORE;
3088 }
3089 else if (strcmp(args[myidx], "store-response") == 0) {
3090 myidx++;
3091 flags = STK_IS_STORE | STK_ON_RSP;
3092 }
3093 else if (strcmp(args[myidx], "match") == 0) {
3094 myidx++;
3095 flags = STK_IS_MATCH;
3096 }
3097 else if (strcmp(args[myidx], "on") == 0) {
3098 myidx++;
3099 flags = STK_IS_MATCH | STK_IS_STORE;
3100 }
3101 else {
3102 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106
3107 if (*(args[myidx]) == 0) {
3108 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
3112
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003113 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003114 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003115 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003116 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
3121 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003122 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3123 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3124 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003125 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003126 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003127 goto out;
3128 }
3129 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003130 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3131 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3132 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003133 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003134 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003135 goto out;
3136 }
3137 }
3138
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003139 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003140 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003141
Emeric Brunb982a3d2010-01-04 15:45:53 +01003142 if (strcmp(args[myidx], "table") == 0) {
3143 myidx++;
3144 name = args[myidx++];
3145 }
3146
Willy Tarreauef6494c2010-01-28 17:12:36 +01003147 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003148 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3149 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3150 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003151 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003152 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003153 goto out;
3154 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003155 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003156 else if (*(args[myidx])) {
3157 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3158 file, linenum, args[0], args[myidx]);
3159 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003160 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003161 goto out;
3162 }
Emeric Brun97679e72010-09-23 17:56:44 +02003163 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003164 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003165 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003166 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003167
Emeric Brunb982a3d2010-01-04 15:45:53 +01003168 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3169 rule->cond = cond;
3170 rule->expr = expr;
3171 rule->flags = flags;
3172 rule->table.name = name ? strdup(name) : NULL;
3173 LIST_INIT(&rule->list);
3174 if (flags & STK_ON_RSP)
3175 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3176 else
3177 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003182
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3184 curproxy->uri_auth = NULL; /* we must detach from the default config */
3185
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003186 if (!*args[1]) {
3187 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003188 } else if (!strcmp(args[1], "admin")) {
3189 struct stats_admin_rule *rule;
3190
3191 if (curproxy == &defproxy) {
3192 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196
3197 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3198 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
3201 }
3202
3203 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3204 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3205 file, linenum, args[0], args[1]);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003209 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3210 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3211 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
3214 }
3215
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003216 err_code |= warnif_cond_conflicts(cond,
3217 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3218 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003219
3220 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3221 rule->cond = cond;
3222 LIST_INIT(&rule->list);
3223 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 } else if (!strcmp(args[1], "uri")) {
3225 if (*(args[2]) == 0) {
3226 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3230 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_ALERT | ERR_ABORT;
3232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 }
3234 } else if (!strcmp(args[1], "realm")) {
3235 if (*(args[2]) == 0) {
3236 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3240 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_ABORT;
3242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003244 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003245 unsigned interval;
3246
3247 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3248 if (err) {
3249 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3250 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003253 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3254 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_ALERT | ERR_ABORT;
3256 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003257 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003258 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003259 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003260
3261 if (curproxy == &defproxy) {
3262 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
3265 }
3266
3267 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3268 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3269 err_code |= ERR_ALERT | ERR_ABORT;
3270 goto out;
3271 }
3272
Willy Tarreauff011f22011-01-06 17:51:27 +01003273 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3274 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003275 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3276 file, linenum, args[0]);
3277 err_code |= ERR_WARN;
3278 }
3279
Willy Tarreauff011f22011-01-06 17:51:27 +01003280 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003281
Willy Tarreauff011f22011-01-06 17:51:27 +01003282 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003283 err_code |= ERR_ALERT | ERR_ABORT;
3284 goto out;
3285 }
3286
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003287 err_code |= warnif_cond_conflicts(rule->cond,
3288 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3289 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003290 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003291
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 } else if (!strcmp(args[1], "auth")) {
3293 if (*(args[2]) == 0) {
3294 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_ABORT;
3300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
3302 } else if (!strcmp(args[1], "scope")) {
3303 if (*(args[2]) == 0) {
3304 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3308 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_ABORT;
3310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
3312 } else if (!strcmp(args[1], "enable")) {
3313 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_ALERT | ERR_ABORT;
3316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003318 } else if (!strcmp(args[1], "hide-version")) {
3319 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3320 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_ABORT;
3322 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003323 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003324 } else if (!strcmp(args[1], "show-legends")) {
3325 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3326 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3327 err_code |= ERR_ALERT | ERR_ABORT;
3328 goto out;
3329 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003330 } else if (!strcmp(args[1], "show-node")) {
3331
3332 if (*args[2]) {
3333 int i;
3334 char c;
3335
3336 for (i=0; args[2][i]; i++) {
3337 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003338 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3339 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003340 break;
3341 }
3342
3343 if (!i || args[2][i]) {
3344 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3345 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3346 file, linenum, args[0], args[1]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350 }
3351
3352 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3353 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3354 err_code |= ERR_ALERT | ERR_ABORT;
3355 goto out;
3356 }
3357 } else if (!strcmp(args[1], "show-desc")) {
3358 char *desc = NULL;
3359
3360 if (*args[2]) {
3361 int i, len=0;
3362 char *d;
3363
3364 for(i=2; *args[i]; i++)
3365 len += strlen(args[i])+1;
3366
3367 desc = d = (char *)calloc(1, len);
3368
3369 d += sprintf(d, "%s", args[2]);
3370 for(i=3; *args[i]; i++)
3371 d += sprintf(d, " %s", args[i]);
3372 }
3373
3374 if (!*args[2] && !global.desc)
3375 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3376 file, linenum, args[1]);
3377 else {
3378 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3379 free(desc);
3380 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3381 err_code |= ERR_ALERT | ERR_ABORT;
3382 goto out;
3383 }
3384 free(desc);
3385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003387stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003388 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 +01003389 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
3393 }
3394 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003395 int optnum;
3396
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003397 if (*(args[1]) == '\0') {
3398 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003403
3404 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3405 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003406 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3407 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3408 file, linenum, cfg_opts[optnum].name);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
Willy Tarreau93893792009-07-23 13:19:11 +02003412 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3413 err_code |= ERR_WARN;
3414 goto out;
3415 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003416
Willy Tarreau3842f002009-06-14 11:39:52 +02003417 curproxy->no_options &= ~cfg_opts[optnum].val;
3418 curproxy->options &= ~cfg_opts[optnum].val;
3419
3420 switch (kwm) {
3421 case KWM_STD:
3422 curproxy->options |= cfg_opts[optnum].val;
3423 break;
3424 case KWM_NO:
3425 curproxy->no_options |= cfg_opts[optnum].val;
3426 break;
3427 case KWM_DEF: /* already cleared */
3428 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003429 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003430
Willy Tarreau93893792009-07-23 13:19:11 +02003431 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003432 }
3433 }
3434
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003435 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3436 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003437 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3438 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3439 file, linenum, cfg_opts2[optnum].name);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
Willy Tarreau93893792009-07-23 13:19:11 +02003443 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3444 err_code |= ERR_WARN;
3445 goto out;
3446 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003447
Willy Tarreau3842f002009-06-14 11:39:52 +02003448 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3449 curproxy->options2 &= ~cfg_opts2[optnum].val;
3450
3451 switch (kwm) {
3452 case KWM_STD:
3453 curproxy->options2 |= cfg_opts2[optnum].val;
3454 break;
3455 case KWM_NO:
3456 curproxy->no_options2 |= cfg_opts2[optnum].val;
3457 break;
3458 case KWM_DEF: /* already cleared */
3459 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003460 }
Willy Tarreau93893792009-07-23 13:19:11 +02003461 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003462 }
3463 }
3464
Willy Tarreau3842f002009-06-14 11:39:52 +02003465 if (kwm != KWM_STD) {
3466 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003467 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003470 }
3471
Emeric Brun3a058f32009-06-30 18:26:00 +02003472 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003473 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003474 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003475 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003476 if (*(args[2]) != '\0') {
3477 if (!strcmp(args[2], "clf")) {
3478 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003479 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003480 } else {
3481 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003484 }
3485 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003486 if (curproxy->conf.logformat_string != default_http_log_format &&
3487 curproxy->conf.logformat_string != default_tcp_log_format &&
3488 curproxy->conf.logformat_string != clf_http_log_format)
3489 free(curproxy->conf.logformat_string);
3490 curproxy->conf.logformat_string = logformat;
3491
3492 free(curproxy->conf.lfs_file);
3493 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3494 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003495 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003496 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003498 if (curproxy->conf.logformat_string != default_http_log_format &&
3499 curproxy->conf.logformat_string != default_tcp_log_format &&
3500 curproxy->conf.logformat_string != clf_http_log_format)
3501 free(curproxy->conf.logformat_string);
3502 curproxy->conf.logformat_string = default_tcp_log_format;
3503
3504 free(curproxy->conf.lfs_file);
3505 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3506 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 else if (!strcmp(args[1], "tcpka")) {
3509 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003510 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003512
3513 if (curproxy->cap & PR_CAP_FE)
3514 curproxy->options |= PR_O_TCP_CLI_KA;
3515 if (curproxy->cap & PR_CAP_BE)
3516 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 }
3518 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_WARN;
3521
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003523 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003524 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003525 curproxy->options2 &= ~PR_O2_CHK_ANY;
3526 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 if (!*args[2]) { /* no argument */
3528 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3529 curproxy->check_len = strlen(DEF_CHECK_REQ);
3530 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003531 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 curproxy->check_req = (char *)malloc(reqlen);
3533 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003534 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003536 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 if (*args[4])
3538 reqlen += strlen(args[4]);
3539 else
3540 reqlen += strlen("HTTP/1.0");
3541
3542 curproxy->check_req = (char *)malloc(reqlen);
3543 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003544 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003546 }
3547 else if (!strcmp(args[1], "ssl-hello-chk")) {
3548 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003549 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003551
Willy Tarreaua534fea2008-08-03 12:19:50 +02003552 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003553 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003554 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003555 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003556 }
Willy Tarreau23677902007-05-08 23:50:35 +02003557 else if (!strcmp(args[1], "smtpchk")) {
3558 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003559 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;
3562 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003563
3564 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3565 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3566 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3567 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3568 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3569 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3570 curproxy->check_req = (char *)malloc(reqlen);
3571 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3572 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3573 } else {
3574 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3575 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3576 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3577 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3578 }
3579 }
3580 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003581 else if (!strcmp(args[1], "pgsql-check")) {
3582 /* use PostgreSQL request to check servers' health */
3583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3584 err_code |= ERR_WARN;
3585
3586 free(curproxy->check_req);
3587 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003588 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003589 curproxy->options2 |= PR_O2_PGSQL_CHK;
3590
3591 if (*(args[2])) {
3592 int cur_arg = 2;
3593
3594 while (*(args[cur_arg])) {
3595 if (strcmp(args[cur_arg], "user") == 0) {
3596 char * packet;
3597 uint32_t packet_len;
3598 uint32_t pv;
3599
3600 /* suboption header - needs additional argument for it */
3601 if (*(args[cur_arg+1]) == 0) {
3602 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3603 file, linenum, args[0], args[1], args[cur_arg]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607
3608 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3609 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3610 pv = htonl(0x30000); /* protocol version 3.0 */
3611
3612 packet = (char*) calloc(1, packet_len);
3613
3614 memcpy(packet + 4, &pv, 4);
3615
3616 /* copy "user" */
3617 memcpy(packet + 8, "user", 4);
3618
3619 /* copy username */
3620 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3621
3622 free(curproxy->check_req);
3623 curproxy->check_req = packet;
3624 curproxy->check_len = packet_len;
3625
3626 packet_len = htonl(packet_len);
3627 memcpy(packet, &packet_len, 4);
3628 cur_arg += 2;
3629 } else {
3630 /* unknown suboption - catchall */
3631 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3632 file, linenum, args[0], args[1]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 } /* end while loop */
3637 }
3638 }
3639
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003640 else if (!strcmp(args[1], "redis-check")) {
3641 /* use REDIS PING request to check servers' health */
3642 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3643 err_code |= ERR_WARN;
3644
3645 free(curproxy->check_req);
3646 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003647 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003648 curproxy->options2 |= PR_O2_REDIS_CHK;
3649
3650 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3651 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3652 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3653 }
3654
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003655 else if (!strcmp(args[1], "mysql-check")) {
3656 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3658 err_code |= ERR_WARN;
3659
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003660 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003661 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003662 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003663 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003664
3665 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3666 * const char mysql40_client_auth_pkt[] = {
3667 * "\x0e\x00\x00" // packet length
3668 * "\x01" // packet number
3669 * "\x00\x00" // client capabilities
3670 * "\x00\x00\x01" // max packet
3671 * "haproxy\x00" // username (null terminated string)
3672 * "\x00" // filler (always 0x00)
3673 * "\x01\x00\x00" // packet length
3674 * "\x00" // packet number
3675 * "\x01" // COM_QUIT command
3676 * };
3677 */
3678
3679 if (*(args[2])) {
3680 int cur_arg = 2;
3681
3682 while (*(args[cur_arg])) {
3683 if (strcmp(args[cur_arg], "user") == 0) {
3684 char *mysqluser;
3685 int packetlen, reqlen, userlen;
3686
3687 /* suboption header - needs additional argument for it */
3688 if (*(args[cur_arg+1]) == 0) {
3689 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3690 file, linenum, args[0], args[1], args[cur_arg]);
3691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
3693 }
3694 mysqluser = args[cur_arg + 1];
3695 userlen = strlen(mysqluser);
3696 packetlen = userlen + 7;
3697 reqlen = packetlen + 9;
3698
3699 free(curproxy->check_req);
3700 curproxy->check_req = (char *)calloc(1, reqlen);
3701 curproxy->check_len = reqlen;
3702
3703 snprintf(curproxy->check_req, 4, "%c%c%c",
3704 ((unsigned char) packetlen & 0xff),
3705 ((unsigned char) (packetlen >> 8) & 0xff),
3706 ((unsigned char) (packetlen >> 16) & 0xff));
3707
3708 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003709 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003710 curproxy->check_req[8] = 1;
3711 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3712 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3713 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3714 cur_arg += 2;
3715 } else {
3716 /* unknown suboption - catchall */
3717 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3718 file, linenum, args[0], args[1]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722 } /* end while loop */
3723 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003724 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003725 else if (!strcmp(args[1], "ldap-check")) {
3726 /* use LDAP request to check servers' health */
3727 free(curproxy->check_req);
3728 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003729 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003730 curproxy->options2 |= PR_O2_LDAP_CHK;
3731
3732 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3733 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3734 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3735 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003736 else if (!strcmp(args[1], "tcp-check")) {
3737 /* use raw TCPCHK send/expect to check servers' health */
3738 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3739 err_code |= ERR_WARN;
3740
3741 free(curproxy->check_req);
3742 curproxy->check_req = NULL;
3743 curproxy->options2 &= ~PR_O2_CHK_ANY;
3744 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3745 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003746 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003747 int cur_arg;
3748
3749 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3750 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003751 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003752
Willy Tarreau87cf5142011-08-19 22:57:24 +02003753 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003754
3755 free(curproxy->fwdfor_hdr_name);
3756 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3757 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3758
3759 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3760 cur_arg = 2;
3761 while (*(args[cur_arg])) {
3762 if (!strcmp(args[cur_arg], "except")) {
3763 /* suboption except - needs additional argument for it */
3764 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3765 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3766 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003769 }
3770 /* flush useless bits */
3771 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003772 cur_arg += 2;
3773 } else if (!strcmp(args[cur_arg], "header")) {
3774 /* suboption header - needs additional argument for it */
3775 if (*(args[cur_arg+1]) == 0) {
3776 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3777 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003780 }
3781 free(curproxy->fwdfor_hdr_name);
3782 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3783 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3784 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003785 } else if (!strcmp(args[cur_arg], "if-none")) {
3786 curproxy->options &= ~PR_O_FF_ALWAYS;
3787 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003788 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003789 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003790 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003791 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003794 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003795 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003796 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003797 else if (!strcmp(args[1], "originalto")) {
3798 int cur_arg;
3799
3800 /* insert x-original-to field, but not for the IP address listed as an except.
3801 * set default options (ie: bitfield, header name, etc)
3802 */
3803
3804 curproxy->options |= PR_O_ORGTO;
3805
3806 free(curproxy->orgto_hdr_name);
3807 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3808 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3809
Willy Tarreau87cf5142011-08-19 22:57:24 +02003810 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003811 cur_arg = 2;
3812 while (*(args[cur_arg])) {
3813 if (!strcmp(args[cur_arg], "except")) {
3814 /* suboption except - needs additional argument for it */
3815 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3816 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3817 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003820 }
3821 /* flush useless bits */
3822 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3823 cur_arg += 2;
3824 } else if (!strcmp(args[cur_arg], "header")) {
3825 /* suboption header - needs additional argument for it */
3826 if (*(args[cur_arg+1]) == 0) {
3827 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3828 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003831 }
3832 free(curproxy->orgto_hdr_name);
3833 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3834 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3835 cur_arg += 2;
3836 } else {
3837 /* unknown suboption - catchall */
3838 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3839 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003842 }
3843 } /* end while loop */
3844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 else {
3846 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 }
Willy Tarreau93893792009-07-23 13:19:11 +02003850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003852 else if (!strcmp(args[0], "default_backend")) {
3853 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003855
3856 if (*(args[1]) == 0) {
3857 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003860 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003861 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003862 curproxy->defbe.name = strdup(args[1]);
3863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003867
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003868 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 /* enable reconnections to dispatch */
3872 curproxy->options |= PR_O_REDISP;
3873 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003874 else if (!strcmp(args[0], "http-check")) {
3875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003877
3878 if (strcmp(args[1], "disable-on-404") == 0) {
3879 /* enable a graceful server shutdown on an HTTP 404 response */
3880 curproxy->options |= PR_O_DISABLE404;
3881 }
Willy Tarreauef781042010-01-27 11:53:01 +01003882 else if (strcmp(args[1], "send-state") == 0) {
3883 /* enable emission of the apparent state of a server in HTTP checks */
3884 curproxy->options2 |= PR_O2_CHK_SNDST;
3885 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003886 else if (strcmp(args[1], "expect") == 0) {
3887 const char *ptr_arg;
3888 int cur_arg;
3889
3890 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3891 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
3896 cur_arg = 2;
3897 /* consider exclamation marks, sole or at the beginning of a word */
3898 while (*(ptr_arg = args[cur_arg])) {
3899 while (*ptr_arg == '!') {
3900 curproxy->options2 ^= PR_O2_EXP_INV;
3901 ptr_arg++;
3902 }
3903 if (*ptr_arg)
3904 break;
3905 cur_arg++;
3906 }
3907 /* now ptr_arg points to the beginning of a word past any possible
3908 * exclamation mark, and cur_arg is the argument which holds this word.
3909 */
3910 if (strcmp(ptr_arg, "status") == 0) {
3911 if (!*(args[cur_arg + 1])) {
3912 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3913 file, linenum, args[0], args[1], ptr_arg);
3914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003918 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003919 curproxy->expect_str = strdup(args[cur_arg + 1]);
3920 }
3921 else if (strcmp(ptr_arg, "string") == 0) {
3922 if (!*(args[cur_arg + 1])) {
3923 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3924 file, linenum, args[0], args[1], ptr_arg);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003929 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003930 curproxy->expect_str = strdup(args[cur_arg + 1]);
3931 }
3932 else if (strcmp(ptr_arg, "rstatus") == 0) {
3933 if (!*(args[cur_arg + 1])) {
3934 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3935 file, linenum, args[0], args[1], ptr_arg);
3936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
3938 }
3939 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003940 free(curproxy->expect_str);
3941 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3942 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003943 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3944 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3945 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3946 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950 }
3951 else if (strcmp(ptr_arg, "rstring") == 0) {
3952 if (!*(args[cur_arg + 1])) {
3953 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3954 file, linenum, args[0], args[1], ptr_arg);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003959 free(curproxy->expect_str);
3960 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3961 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003962 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3963 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3964 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3965 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969 }
3970 else {
3971 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3972 file, linenum, args[0], args[1], ptr_arg);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
3976 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003977 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003978 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 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003981 }
3982 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003983 else if (!strcmp(args[0], "tcp-check")) {
3984 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3985 err_code |= ERR_WARN;
3986
3987 if (strcmp(args[1], "send") == 0) {
3988 if (! *(args[2]) ) {
3989 /* SEND string expected */
3990 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
3991 file, linenum, args[0], args[1], args[2]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 } else {
3995 struct tcpcheck_rule *tcpcheck;
3996
3997 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
3998
3999 tcpcheck->action = TCPCHK_ACT_SEND;
4000 tcpcheck->string_len = strlen(args[2]);
4001 tcpcheck->string = strdup(args[2]);
4002 tcpcheck->expect_regex = NULL;
4003
4004 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4005 }
4006 }
4007 else if (strcmp(args[1], "send-binary") == 0) {
4008 if (! *(args[2]) ) {
4009 /* SEND binary string expected */
4010 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4011 file, linenum, args[0], args[1], args[2]);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 } else {
4015 struct tcpcheck_rule *tcpcheck;
4016 char *err = NULL;
4017
4018 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4019
4020 tcpcheck->action = TCPCHK_ACT_SEND;
4021 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4022 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4023 file, linenum, args[0], args[1], args[2], err);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027 tcpcheck->expect_regex = NULL;
4028
4029 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4030 }
4031 }
4032 else if (strcmp(args[1], "expect") == 0) {
4033 const char *ptr_arg;
4034 int cur_arg;
4035 int inverse = 0;
4036
4037 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4038 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042
4043 cur_arg = 2;
4044 /* consider exclamation marks, sole or at the beginning of a word */
4045 while (*(ptr_arg = args[cur_arg])) {
4046 while (*ptr_arg == '!') {
4047 inverse = !inverse;
4048 ptr_arg++;
4049 }
4050 if (*ptr_arg)
4051 break;
4052 cur_arg++;
4053 }
4054 /* now ptr_arg points to the beginning of a word past any possible
4055 * exclamation mark, and cur_arg is the argument which holds this word.
4056 */
4057 if (strcmp(ptr_arg, "binary") == 0) {
4058 if (!*(args[cur_arg + 1])) {
4059 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4060 file, linenum, args[0], args[1], ptr_arg);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
4064 struct tcpcheck_rule *tcpcheck;
4065 char *err = NULL;
4066
4067 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4068
4069 tcpcheck->action = TCPCHK_ACT_EXPECT;
4070 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4071 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4072 file, linenum, args[0], args[1], args[2], err);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 tcpcheck->expect_regex = NULL;
4077 tcpcheck->inverse = inverse;
4078
4079 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4080 }
4081 else if (strcmp(ptr_arg, "string") == 0) {
4082 if (!*(args[cur_arg + 1])) {
4083 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4084 file, linenum, args[0], args[1], ptr_arg);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
4088 struct tcpcheck_rule *tcpcheck;
4089
4090 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4091
4092 tcpcheck->action = TCPCHK_ACT_EXPECT;
4093 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4094 tcpcheck->string = strdup(args[cur_arg + 1]);
4095 tcpcheck->expect_regex = NULL;
4096 tcpcheck->inverse = inverse;
4097
4098 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4099 }
4100 else if (strcmp(ptr_arg, "rstring") == 0) {
4101 if (!*(args[cur_arg + 1])) {
4102 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4103 file, linenum, args[0], args[1], ptr_arg);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
4107 struct tcpcheck_rule *tcpcheck;
4108
4109 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4110
4111 tcpcheck->action = TCPCHK_ACT_EXPECT;
4112 tcpcheck->string_len = 0;
4113 tcpcheck->string = NULL;
4114 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4115 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4116 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4117 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121 tcpcheck->inverse = inverse;
4122
4123 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4124 }
4125 else {
4126 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4127 file, linenum, args[0], args[1], ptr_arg);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 }
4132 else {
4133 Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004138 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004139 if (curproxy == &defproxy) {
4140 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004143 }
4144
Willy Tarreaub80c2302007-11-30 20:51:32 +01004145 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004147
4148 if (strcmp(args[1], "fail") == 0) {
4149 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004150 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004151 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4152 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004155 }
4156
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004157 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4158 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4159 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004162 }
4163 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4164 }
4165 else {
4166 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004169 }
4170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171#ifdef TPROXY
4172 else if (!strcmp(args[0], "transparent")) {
4173 /* enable transparent proxy connections */
4174 curproxy->options |= PR_O_TRANSP;
4175 }
4176#endif
4177 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004178 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004179 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004180
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 if (*(args[1]) == 0) {
4182 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 }
4186 curproxy->maxconn = atol(args[1]);
4187 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004188 else if (!strcmp(args[0], "backlog")) { /* backlog */
4189 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004191
4192 if (*(args[1]) == 0) {
4193 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004196 }
4197 curproxy->backlog = atol(args[1]);
4198 }
Willy Tarreau86034312006-12-29 00:10:33 +01004199 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004200 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004202
Willy Tarreau86034312006-12-29 00:10:33 +01004203 if (*(args[1]) == 0) {
4204 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004207 }
4208 curproxy->fullconn = atol(args[1]);
4209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4211 if (*(args[1]) == 0) {
4212 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004216 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4217 if (err) {
4218 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4219 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004222 }
4223 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 }
4225 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004226 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004227 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004228 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004229
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230 if (curproxy == &defproxy) {
4231 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004235 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004237
Willy Tarreau902636f2013-03-10 19:44:48 +01004238 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004239 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004240 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004241 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004242 goto out;
4243 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004244
4245 proto = protocol_by_family(sk->ss_family);
4246 if (!proto || !proto->connect) {
4247 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4248 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251 }
4252
4253 if (port1 != port2) {
4254 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4255 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004259
4260 if (!port1) {
4261 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4262 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004266
Willy Tarreaud5191e72010-02-09 20:50:45 +01004267 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004268 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 }
4270 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004273
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004274 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4275 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004278 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004280 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004281 /**
4282 * The syntax for hash-type config element is
4283 * hash-type {map-based|consistent} [[<algo>] avalanche]
4284 *
4285 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4286 */
4287 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004288
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004289 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4290 err_code |= ERR_WARN;
4291
4292 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004293 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4294 }
4295 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004296 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4297 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004298 else if (strcmp(args[1], "avalanche") == 0) {
4299 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004302 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004303 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004304 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004305 err_code |= ERR_ALERT | ERR_FATAL;
4306 goto out;
4307 }
Bhaskar98634f02013-10-29 23:30:51 -04004308
4309 /* set the hash function to use */
4310 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004311 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004312 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004313
4314 /* if consistent with no argument, then avalanche modifier is also applied */
4315 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4316 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004317 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004318 /* set the hash function */
4319 if (!strcmp(args[2], "sdbm")) {
4320 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4321 }
4322 else if (!strcmp(args[2], "djb2")) {
4323 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004324 } else if (!strcmp(args[2], "wt6")) {
4325 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004326 }
4327 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004328 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332
4333 /* set the hash modifier */
4334 if (!strcmp(args[3], "avalanche")) {
4335 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4336 }
4337 else if (*args[3]) {
4338 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
Bhaskar98634f02013-10-29 23:30:51 -04004342 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004343 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004344 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004346 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004347 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004349 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004354 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004355 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356
4357 if (!*args[2]) {
4358 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004363
4364 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004365 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004366 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4367 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004370 }
4371
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004372 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004373 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004374 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004375 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004376
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004377 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4378 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4379 err_code |= ERR_ALERT | ERR_ABORT;
4380 goto out;
4381 }
4382
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004383 /* the servers are linked backwards first */
4384 newsrv->next = curproxy->srv;
4385 curproxy->srv = newsrv;
4386 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004387 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004388 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004390 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004391 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004392 LIST_INIT(&newsrv->pendconns);
4393 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004394 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004395 newsrv->state = SRV_RUNNING; /* early server setup */
4396 newsrv->last_change = now.tv_sec;
4397 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004399 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004400 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004401 * - IP: => port=+0, relative
4402 * - IP:N => port=N, absolute
4403 * - IP:+N => port=+N, relative
4404 * - IP:-N => port=-N, relative
4405 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004406 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004407 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004408 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004409 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004410 goto out;
4411 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004412
4413 proto = protocol_by_family(sk->ss_family);
4414 if (!proto || !proto->connect) {
4415 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4416 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004420
4421 if (!port1 || !port2) {
4422 /* no port specified, +offset, -offset */
4423 newsrv->state |= SRV_MAPPORTS;
4424 }
4425 else if (port1 != port2) {
4426 /* port range */
4427 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4428 file, linenum, args[0], args[1], args[2]);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
4432 else {
4433 /* used by checks */
4434 realport = port1;
4435 }
4436
Willy Tarreaud5191e72010-02-09 20:50:45 +01004437 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004438 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4439 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004440
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004441 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004442 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4443 file, linenum, newsrv->addr.ss_family, args[2]);
4444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
4446 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004447
Simon Hormand60d6912013-11-25 10:46:36 +09004448 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004449 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004450 newsrv->check.inter = curproxy->defsrv.check.inter;
4451 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4452 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004453 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4454 newsrv->agent.port = curproxy->defsrv.agent.port;
4455 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4456 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4457 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004458 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4459 newsrv->minconn = curproxy->defsrv.minconn;
4460 newsrv->maxconn = curproxy->defsrv.maxconn;
4461 newsrv->slowstart = curproxy->defsrv.slowstart;
4462 newsrv->onerror = curproxy->defsrv.onerror;
4463 newsrv->consecutive_errors_limit
4464 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004465#ifdef OPENSSL
4466 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4467#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004468 newsrv->uweight = newsrv->iweight
4469 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470
Simon Horman69d29f92013-02-23 15:14:19 +09004471 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004472 newsrv->check.rise = curproxy->defsrv.check.rise;
4473 newsrv->check.fall = curproxy->defsrv.check.fall;
4474 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004475 newsrv->check.server = newsrv;
4476
Simon Hormand60d6912013-11-25 10:46:36 +09004477 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004478 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4479 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4480 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004481 newsrv->agent.server = newsrv;
4482
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004483 cur_arg = 3;
4484 } else {
4485 newsrv = &curproxy->defsrv;
4486 cur_arg = 1;
4487 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004488
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004490 if (!strcmp(args[cur_arg], "agent-check")) {
4491 global.maxsock++;
4492 do_agent = 1;
4493 cur_arg += 1;
4494 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4495 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4496 if (err) {
4497 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4498 file, linenum, *err, newsrv->id);
4499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
4501 }
4502 if (val <= 0) {
4503 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4504 file, linenum, val, args[cur_arg], newsrv->id);
4505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
4508 newsrv->agent.inter = val;
4509 cur_arg += 2;
4510 }
4511 else if (!strcmp(args[cur_arg], "agent-port")) {
4512 global.maxsock++;
4513 newsrv->agent.port = atol(args[cur_arg + 1]);
4514 cur_arg += 2;
4515 }
4516 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 newsrv->cookie = strdup(args[cur_arg + 1]);
4518 newsrv->cklen = strlen(args[cur_arg + 1]);
4519 cur_arg += 2;
4520 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004521 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004522 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4523 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4524 cur_arg += 2;
4525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004527 if (!*args[cur_arg + 1]) {
4528 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4529 file, linenum, args[cur_arg]);
4530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
4532 }
4533
Simon Horman58c32972013-11-25 10:46:38 +09004534 newsrv->check.rise = atol(args[cur_arg + 1]);
4535 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004536 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4537 file, linenum, args[cur_arg]);
4538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
4540 }
4541
Simon Horman125d0992013-02-24 17:23:38 +09004542 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004543 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 cur_arg += 2;
4545 }
4546 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004547 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004548
4549 if (!*args[cur_arg + 1]) {
4550 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4551 file, linenum, args[cur_arg]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555
Simon Horman58c32972013-11-25 10:46:38 +09004556 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004557 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4558 file, linenum, args[cur_arg]);
4559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
4561 }
4562
Willy Tarreaubaaee002006-06-26 02:48:02 +02004563 cur_arg += 2;
4564 }
4565 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004566 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4567 if (err) {
4568 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4569 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004572 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004573 if (val <= 0) {
4574 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4575 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004578 }
Simon Horman66183002013-02-23 10:16:43 +09004579 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 cur_arg += 2;
4581 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004582 else if (!strcmp(args[cur_arg], "fastinter")) {
4583 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4584 if (err) {
4585 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4586 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004589 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004590 if (val <= 0) {
4591 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4592 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004595 }
Simon Horman66183002013-02-23 10:16:43 +09004596 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004597 cur_arg += 2;
4598 }
4599 else if (!strcmp(args[cur_arg], "downinter")) {
4600 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4601 if (err) {
4602 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4603 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004606 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004607 if (val <= 0) {
4608 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4609 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004612 }
Simon Horman66183002013-02-23 10:16:43 +09004613 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004614 cur_arg += 2;
4615 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004616 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004617 struct sockaddr_storage *sk;
4618 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004619 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004620
Willy Tarreau902636f2013-03-10 19:44:48 +01004621 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004622 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004623 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004624 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004626 goto out;
4627 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004628
4629 proto = protocol_by_family(sk->ss_family);
4630 if (!proto || !proto->connect) {
4631 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004632 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004636
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004637 if (port1 != port2) {
4638 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4639 file, linenum, args[cur_arg], args[cur_arg + 1]);
4640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
4643
Simon Horman66183002013-02-23 10:16:43 +09004644 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004645 cur_arg += 2;
4646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004648 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 cur_arg += 2;
4650 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004651 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 newsrv->state |= SRV_BACKUP;
4653 cur_arg ++;
4654 }
Simon Hormanfa461682011-06-25 09:39:49 +09004655 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4656 newsrv->state |= SRV_NON_STICK;
4657 cur_arg ++;
4658 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004659 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4660 newsrv->state |= SRV_SEND_PROXY;
4661 cur_arg ++;
4662 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004663 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4664 newsrv->check.send_proxy = 1;
4665 cur_arg ++;
4666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 else if (!strcmp(args[cur_arg], "weight")) {
4668 int w;
4669 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004670 if (w < 0 || w > SRV_UWGHT_MAX) {
4671 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4672 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004673 err_code |= ERR_ALERT | ERR_FATAL;
4674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004676 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 cur_arg += 2;
4678 }
4679 else if (!strcmp(args[cur_arg], "minconn")) {
4680 newsrv->minconn = atol(args[cur_arg + 1]);
4681 cur_arg += 2;
4682 }
4683 else if (!strcmp(args[cur_arg], "maxconn")) {
4684 newsrv->maxconn = atol(args[cur_arg + 1]);
4685 cur_arg += 2;
4686 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004687 else if (!strcmp(args[cur_arg], "maxqueue")) {
4688 newsrv->maxqueue = atol(args[cur_arg + 1]);
4689 cur_arg += 2;
4690 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004691 else if (!strcmp(args[cur_arg], "slowstart")) {
4692 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004693 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004694 if (err) {
4695 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4696 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004699 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004700 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004701 cur_arg += 2;
4702 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004703 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004704
4705 if (!*args[cur_arg + 1]) {
4706 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4707 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004710 }
4711
4712 newsrv->trackit = strdup(args[cur_arg + 1]);
4713
4714 cur_arg += 2;
4715 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004716 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 global.maxsock++;
4718 do_check = 1;
4719 cur_arg += 1;
4720 }
Willy Tarreau96839092010-03-29 10:02:24 +02004721 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4722 newsrv->state |= SRV_MAINTAIN;
4723 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004724 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004725 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004726 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004727 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004728 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004729 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004730 if (!strcmp(args[cur_arg + 1], "none"))
4731 newsrv->observe = HANA_OBS_NONE;
4732 else if (!strcmp(args[cur_arg + 1], "layer4"))
4733 newsrv->observe = HANA_OBS_LAYER4;
4734 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4735 if (curproxy->mode != PR_MODE_HTTP) {
4736 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4737 file, linenum, args[cur_arg + 1]);
4738 err_code |= ERR_ALERT;
4739 }
4740 newsrv->observe = HANA_OBS_LAYER7;
4741 }
4742 else {
4743 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004744 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004745 file, linenum, args[cur_arg], args[cur_arg + 1]);
4746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
4748 }
4749
4750 cur_arg += 2;
4751 }
4752 else if (!strcmp(args[cur_arg], "on-error")) {
4753 if (!strcmp(args[cur_arg + 1], "fastinter"))
4754 newsrv->onerror = HANA_ONERR_FASTINTER;
4755 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4756 newsrv->onerror = HANA_ONERR_FAILCHK;
4757 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4758 newsrv->onerror = HANA_ONERR_SUDDTH;
4759 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4760 newsrv->onerror = HANA_ONERR_MARKDWN;
4761 else {
4762 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004763 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004764 file, linenum, args[cur_arg], args[cur_arg + 1]);
4765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
4767 }
4768
4769 cur_arg += 2;
4770 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004771 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4772 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4773 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4774 else {
4775 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4776 file, linenum, args[cur_arg], args[cur_arg + 1]);
4777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
4780
4781 cur_arg += 2;
4782 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004783 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4784 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4785 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4786 else {
4787 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4788 file, linenum, args[cur_arg], args[cur_arg + 1]);
4789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791 }
4792
4793 cur_arg += 2;
4794 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004795 else if (!strcmp(args[cur_arg], "error-limit")) {
4796 if (!*args[cur_arg + 1]) {
4797 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4798 file, linenum, args[cur_arg]);
4799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
4802
4803 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4804
4805 if (newsrv->consecutive_errors_limit <= 0) {
4806 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4807 file, linenum, args[cur_arg]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004811 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004812 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004813 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004814 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004815 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004816 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004817
Willy Tarreaubaaee002006-06-26 02:48:02 +02004818 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004819 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4820 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004824
Willy Tarreauef9a3602012-12-08 22:29:20 +01004825 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004826 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004827 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004828 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004829 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004830 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004831 goto out;
4832 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004833
4834 proto = protocol_by_family(sk->ss_family);
4835 if (!proto || !proto->connect) {
4836 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4837 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004838 err_code |= ERR_ALERT | ERR_FATAL;
4839 goto out;
4840 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004841
Willy Tarreauef9a3602012-12-08 22:29:20 +01004842 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004843
4844 if (port_low != port_high) {
4845 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004846
4847 if (!port_low || !port_high) {
4848 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4849 file, linenum, args[cur_arg], args[cur_arg + 1]);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
4853
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004854 if (port_low <= 0 || port_low > 65535 ||
4855 port_high <= 0 || port_high > 65535 ||
4856 port_low > port_high) {
4857 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4858 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004861 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004862 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4863 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4864 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004865 }
4866
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004868 while (*(args[cur_arg])) {
4869 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004870#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4871#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004872 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004873 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4874 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004877 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004878#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004879 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004880 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004881 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004884 }
4885 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004886 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4887 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004888 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004889 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4890 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004891 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4892 char *name, *end;
4893
4894 name = args[cur_arg+1] + 7;
4895 while (isspace(*name))
4896 name++;
4897
4898 end = name;
4899 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4900 end++;
4901
Willy Tarreauef9a3602012-12-08 22:29:20 +01004902 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4903 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4904 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4905 newsrv->conn_src.bind_hdr_len = end - name;
4906 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4907 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4908 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004909
4910 /* now look for an occurrence number */
4911 while (isspace(*end))
4912 end++;
4913 if (*end == ',') {
4914 end++;
4915 name = end;
4916 if (*end == '-')
4917 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004918 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004919 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004920 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004921 }
4922
Willy Tarreauef9a3602012-12-08 22:29:20 +01004923 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004924 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4925 " occurrences values smaller than %d.\n",
4926 file, linenum, MAX_HDR_HISTORY);
4927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
4929 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004930 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004931 struct sockaddr_storage *sk;
4932 int port1, port2;
4933
Willy Tarreau902636f2013-03-10 19:44:48 +01004934 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004935 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004936 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004937 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004938 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004939 goto out;
4940 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004941
4942 proto = protocol_by_family(sk->ss_family);
4943 if (!proto || !proto->connect) {
4944 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4945 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004949
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004950 if (port1 != port2) {
4951 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4952 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
4955 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004956 newsrv->conn_src.tproxy_addr = *sk;
4957 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004958 }
4959 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004960#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004961 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004962#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004963 cur_arg += 2;
4964 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004965#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004966 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004967 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004970#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004971 } /* "usesrc" */
4972
4973 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4974#ifdef SO_BINDTODEVICE
4975 if (!*args[cur_arg + 1]) {
4976 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4977 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004980 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004981 free(newsrv->conn_src.iface_name);
4982 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4983 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004984 global.last_checks |= LSTCHK_NETADM;
4985#else
4986 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4987 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004990#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004991 cur_arg += 2;
4992 continue;
4993 }
4994 /* this keyword in not an option of "source" */
4995 break;
4996 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004998 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004999 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5000 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005005 static int srv_dumped;
5006 struct srv_kw *kw;
5007 char *err;
5008
5009 kw = srv_find_kw(args[cur_arg]);
5010 if (kw) {
5011 char *err = NULL;
5012 int code;
5013
5014 if (!kw->parse) {
5015 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5016 file, linenum, args[0], args[1], args[cur_arg]);
5017 cur_arg += 1 + kw->skip ;
5018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
5020 }
5021
5022 if (defsrv && !kw->default_ok) {
5023 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5024 file, linenum, args[0], args[1], args[cur_arg]);
5025 cur_arg += 1 + kw->skip ;
5026 err_code |= ERR_ALERT;
5027 continue;
5028 }
5029
5030 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5031 err_code |= code;
5032
5033 if (code) {
5034 if (err && *err) {
5035 indent_msg(&err, 2);
5036 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5037 }
5038 else
5039 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5040 file, linenum, args[0], args[1], args[cur_arg]);
5041 if (code & ERR_FATAL) {
5042 free(err);
5043 cur_arg += 1 + kw->skip;
5044 goto out;
5045 }
5046 }
5047 free(err);
5048 cur_arg += 1 + kw->skip;
5049 continue;
5050 }
5051
5052 err = NULL;
5053 if (!srv_dumped) {
5054 srv_dump_kws(&err);
5055 indent_msg(&err, 4);
5056 srv_dumped = 1;
5057 }
5058
5059 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5060 file, linenum, args[0], args[1], args[cur_arg],
5061 err ? " Registered keywords :" : "", err ? err : "");
5062 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005063
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
5067 }
5068
Simon Horman8c3d0be2013-11-25 10:46:40 +09005069 /* Set initial drain state using now-configured weight */
5070 set_server_drain_state(newsrv);
5071
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005073 int ret;
5074
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005075 if (newsrv->trackit) {
5076 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5077 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005080 }
5081
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005082 /* If neither a port nor an addr was specified and no check transport
5083 * layer is forced, then the transport layer used by the checks is the
5084 * same as for the production traffic. Otherwise we use raw_sock by
5085 * default, unless one is specified.
5086 */
Simon Horman66183002013-02-23 10:16:43 +09005087 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005088#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005089 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02005090#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005091 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5092 }
Simon Horman66183002013-02-23 10:16:43 +09005093 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005094 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005095 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005096
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005097 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005098 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005099
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005100 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005101 /* not yet valid, because no port was set on
5102 * the server either. We'll check if we have
5103 * a known port on the first listener.
5104 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005105 struct listener *l;
5106
5107 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005108 newsrv->check.port = get_host_port(&l->addr);
5109 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005110 break;
5111 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005112 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005113 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5115 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005119
Willy Tarreau2f075e92013-12-03 11:11:34 +01005120 /* note: check type will be set during the config review phase */
5121 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005122 if (ret) {
5123 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005124 goto out;
5125 }
5126
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005127 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
5129
Simon Hormand60d6912013-11-25 10:46:36 +09005130 if (do_agent) {
5131 int ret;
5132
5133 if (!newsrv->agent.port) {
5134 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5135 file, linenum, newsrv->id);
5136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
5138 }
5139
5140 if (!newsrv->agent.inter)
5141 newsrv->agent.inter = newsrv->check.inter;
5142
5143 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5144 if (ret) {
5145 err_code |= ret;
5146 goto out;
5147 }
5148
Willy Tarreau33434322013-12-11 21:15:19 +01005149 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005150 }
5151
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005152 if (!defsrv) {
5153 if (newsrv->state & SRV_BACKUP)
5154 curproxy->srv_bck++;
5155 else
5156 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005157
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005158 newsrv->prev_state = newsrv->state;
5159 }
William Lallemanda73203e2012-03-12 12:48:57 +01005160 }
5161
5162 else if (strcmp(args[0], "unique-id-format") == 0) {
5163 if (!*(args[1])) {
5164 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
5167 }
William Lallemand3203ff42012-11-11 17:30:56 +01005168 if (*(args[2])) {
5169 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
5172 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005173 free(curproxy->conf.uniqueid_format_string);
5174 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005175
Willy Tarreau62a61232013-04-12 18:13:46 +02005176 free(curproxy->conf.uif_file);
5177 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5178 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005179 }
William Lallemanda73203e2012-03-12 12:48:57 +01005180
5181 else if (strcmp(args[0], "unique-id-header") == 0) {
5182 if (!*(args[1])) {
5183 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
5186 }
5187 free(curproxy->header_unique_id);
5188 curproxy->header_unique_id = strdup(args[1]);
5189 }
5190
William Lallemand723b73a2012-02-08 16:37:49 +01005191 else if (strcmp(args[0], "log-format") == 0) {
5192 if (!*(args[1])) {
5193 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
5196 }
William Lallemand3203ff42012-11-11 17:30:56 +01005197 if (*(args[2])) {
5198 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
5201 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005202
Willy Tarreau62a61232013-04-12 18:13:46 +02005203 if (curproxy->conf.logformat_string != default_http_log_format &&
5204 curproxy->conf.logformat_string != default_tcp_log_format &&
5205 curproxy->conf.logformat_string != clf_http_log_format)
5206 free(curproxy->conf.logformat_string);
5207 curproxy->conf.logformat_string = strdup(args[1]);
5208
5209 free(curproxy->conf.lfs_file);
5210 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5211 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005212
5213 /* get a chance to improve log-format error reporting by
5214 * reporting the correct line-number when possible.
5215 */
5216 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5217 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5218 file, linenum, curproxy->id);
5219 err_code |= ERR_WARN;
5220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
William Lallemand723b73a2012-02-08 16:37:49 +01005222
William Lallemand0f99e342011-10-12 17:50:54 +02005223 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5224 /* delete previous herited or defined syslog servers */
5225 struct logsrv *back;
5226
5227 if (*(args[1]) != 0) {
5228 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231 }
5232
William Lallemand723b73a2012-02-08 16:37:49 +01005233 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5234 LIST_DEL(&tmplogsrv->list);
5235 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005236 }
5237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005239 struct logsrv *logsrv;
5240
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005242 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005243 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005244 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005245 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005246 LIST_INIT(&node->list);
5247 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
5250 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005251 struct sockaddr_storage *sk;
5252 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005253
5254 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255
William Lallemand0f99e342011-10-12 17:50:54 +02005256 logsrv->facility = get_log_facility(args[2]);
5257 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 }
5263
William Lallemand0f99e342011-10-12 17:50:54 +02005264 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005266 logsrv->level = get_log_level(args[3]);
5267 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 }
5274
William Lallemand0f99e342011-10-12 17:50:54 +02005275 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005276 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005277 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005278 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005279 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005283 }
5284 }
5285
Willy Tarreau902636f2013-03-10 19:44:48 +01005286 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005287 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005288 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005289 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005290 goto out;
5291 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005292
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005293 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005294
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005295 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005296 if (port1 != port2) {
5297 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5298 file, linenum, args[0], args[1]);
5299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
5301 }
5302
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005303 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005304 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
William Lallemand0f99e342011-10-12 17:50:54 +02005306
5307 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 }
5309 else {
5310 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5311 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
5315 }
5316 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005317 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005318 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005319 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005320 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005321
Willy Tarreau977b8e42006-12-29 14:19:17 +01005322 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005323 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005324
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005326 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5327 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005331
5332 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005333 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5334 free(curproxy->conn_src.iface_name);
5335 curproxy->conn_src.iface_name = NULL;
5336 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005337
Willy Tarreau902636f2013-03-10 19:44:48 +01005338 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005339 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005340 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005341 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005342 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005343 goto out;
5344 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005345
5346 proto = protocol_by_family(sk->ss_family);
5347 if (!proto || !proto->connect) {
5348 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005349 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005353
5354 if (port1 != port2) {
5355 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5356 file, linenum, args[0], args[1]);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360
Willy Tarreauef9a3602012-12-08 22:29:20 +01005361 curproxy->conn_src.source_addr = *sk;
5362 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005363
5364 cur_arg = 2;
5365 while (*(args[cur_arg])) {
5366 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005367#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5368#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005369 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005370 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5371 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005374 }
5375#endif
5376 if (!*args[cur_arg + 1]) {
5377 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5378 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005381 }
5382
5383 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005384 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5385 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005386 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005387 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5388 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005389 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5390 char *name, *end;
5391
5392 name = args[cur_arg+1] + 7;
5393 while (isspace(*name))
5394 name++;
5395
5396 end = name;
5397 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5398 end++;
5399
Willy Tarreauef9a3602012-12-08 22:29:20 +01005400 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5401 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5402 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5403 curproxy->conn_src.bind_hdr_len = end - name;
5404 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5405 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5406 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005407
5408 /* now look for an occurrence number */
5409 while (isspace(*end))
5410 end++;
5411 if (*end == ',') {
5412 end++;
5413 name = end;
5414 if (*end == '-')
5415 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005416 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005417 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005418 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005419 }
5420
Willy Tarreauef9a3602012-12-08 22:29:20 +01005421 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005422 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5423 " occurrences values smaller than %d.\n",
5424 file, linenum, MAX_HDR_HISTORY);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005428 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005429 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005430
Willy Tarreau902636f2013-03-10 19:44:48 +01005431 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005432 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005433 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005434 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005435 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005436 goto out;
5437 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005438
5439 proto = protocol_by_family(sk->ss_family);
5440 if (!proto || !proto->connect) {
5441 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5442 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005446
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005447 if (port1 != port2) {
5448 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5449 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005453 curproxy->conn_src.tproxy_addr = *sk;
5454 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005455 }
5456 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005457#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005458 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005459#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005460#else /* no TPROXY support */
5461 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005462 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005465#endif
5466 cur_arg += 2;
5467 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005468 }
5469
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005470 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5471#ifdef SO_BINDTODEVICE
5472 if (!*args[cur_arg + 1]) {
5473 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5474 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005477 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005478 free(curproxy->conn_src.iface_name);
5479 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5480 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005481 global.last_checks |= LSTCHK_NETADM;
5482#else
5483 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5484 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005487#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005488 cur_arg += 2;
5489 continue;
5490 }
5491 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005492 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005497 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5498 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5499 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005504 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5506 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005510
5511 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005512 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005513 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005514 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 }
5517 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005518 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005519 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005520 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005521 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
5524 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005525 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005526 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005527 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005528 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 }
5531 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005532 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005533 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005534 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005535 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 }
5538 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005539 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005540 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005541 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005542 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005545 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005546 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005547 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005548 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005549 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005550 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005551 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005552 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005553 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005554 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005555 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005556 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005557 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005558 }
5559 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005560 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005561 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005562 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005563 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005564 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005567 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5569 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005573
5574 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005575 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005576 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005577 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 }
5580 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005581 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005582 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005583 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005584 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 }
5587 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005588 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005589 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005590 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005591 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 }
5594 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005595 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005596 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005597 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005598 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 }
5601 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005602 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005603 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005604 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005605 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005608 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005609 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005610 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005611 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005612 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005613 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005616 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005617
Willy Tarreaubaaee002006-06-26 02:48:02 +02005618 if (curproxy == &defproxy) {
5619 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005623 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005624 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626 if (*(args[1]) == 0) {
5627 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005631
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005632 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005633 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5634 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5635 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005636 err_code |= ERR_ALERT | ERR_FATAL;
5637 goto out;
5638 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005639 err_code |= warnif_cond_conflicts(cond,
5640 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5641 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005642 }
5643 else if (*args[2]) {
5644 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5645 file, linenum, args[0], args[2]);
5646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
5649
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005650 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005651 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005652 wl->s = strdup(args[1]);
5653 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005654 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
5656 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005657 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005663
Willy Tarreauade5ec42010-01-28 19:33:49 +01005664 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005665 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005666 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005667 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005671 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005672 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005673 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005674 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
5677 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005678 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005679 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005680 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005681 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
5684 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005685 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5687 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690 }
5691
Willy Tarreauade5ec42010-01-28 19:33:49 +01005692 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005693 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005694 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005695 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 }
5698 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005699 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005700 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005701 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005702 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704 }
5705 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005706 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005707 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005708 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005709 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 }
5712 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005713 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005714
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 if (curproxy == &defproxy) {
5716 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005720 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723 if (*(args[1]) == 0) {
5724 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
5728
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005729 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005730 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5731 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5732 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
5735 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005736 err_code |= warnif_cond_conflicts(cond,
5737 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5738 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005739 }
5740 else if (*args[2]) {
5741 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5742 file, linenum, args[0], args[2]);
5743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
5745 }
5746
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005747 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005748 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005749 wl->s = strdup(args[1]);
5750 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 }
5752 else if (!strcmp(args[0], "errorloc") ||
5753 !strcmp(args[0], "errorloc302") ||
5754 !strcmp(args[0], "errorloc303")) { /* error location */
5755 int errnum, errlen;
5756 char *err;
5757
Willy Tarreau977b8e42006-12-29 14:19:17 +01005758 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005759 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005760
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005762 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 }
5766
5767 errnum = atol(args[1]);
5768 if (!strcmp(args[0], "errorloc303")) {
5769 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5770 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5771 } else {
5772 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5773 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5774 }
5775
Willy Tarreau0f772532006-12-23 20:51:41 +01005776 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5777 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005778 chunk_destroy(&curproxy->errmsg[rc]);
5779 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005780 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005783
5784 if (rc >= HTTP_ERR_SIZE) {
5785 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5786 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 free(err);
5788 }
5789 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005790 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5791 int errnum, errlen, fd;
5792 char *err;
5793 struct stat stat;
5794
5795 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005797
5798 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005799 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005802 }
5803
5804 fd = open(args[2], O_RDONLY);
5805 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5806 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5807 file, linenum, args[2], args[1]);
5808 if (fd >= 0)
5809 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005810 err_code |= ERR_ALERT | ERR_FATAL;
5811 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005812 }
5813
Willy Tarreau27a674e2009-08-17 07:23:33 +02005814 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005815 errlen = stat.st_size;
5816 } else {
5817 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005818 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005819 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005820 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005821 }
5822
5823 err = malloc(errlen); /* malloc() must succeed during parsing */
5824 errnum = read(fd, err, errlen);
5825 if (errnum != errlen) {
5826 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5827 file, linenum, args[2], args[1]);
5828 close(fd);
5829 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005832 }
5833 close(fd);
5834
5835 errnum = atol(args[1]);
5836 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5837 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005838 chunk_destroy(&curproxy->errmsg[rc]);
5839 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005840 break;
5841 }
5842 }
5843
5844 if (rc >= HTTP_ERR_SIZE) {
5845 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5846 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005847 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005848 free(err);
5849 }
5850 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005851 else if (!strcmp(args[0], "compression")) {
5852 struct comp *comp;
5853 if (curproxy->comp == NULL) {
5854 comp = calloc(1, sizeof(struct comp));
5855 curproxy->comp = comp;
5856 } else {
5857 comp = curproxy->comp;
5858 }
5859
5860 if (!strcmp(args[1], "algo")) {
5861 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005862 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005863
William Lallemand82fe75c2012-10-23 10:25:10 +02005864 cur_arg = 2;
5865 if (!*args[cur_arg]) {
5866 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5867 file, linenum, args[0]);
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
5870 }
5871 while (*(args[cur_arg])) {
5872 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5873 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5874 file, linenum, args[0], args[cur_arg]);
5875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877 }
William Lallemand552df672012-11-07 13:21:47 +01005878 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5879 curproxy->comp->algos->end(&ctx);
5880 } else {
5881 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5882 file, linenum, args[0], args[cur_arg]);
5883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
5885 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005886 cur_arg ++;
5887 continue;
5888 }
5889 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005890 else if (!strcmp(args[1], "offload")) {
5891 comp->offload = 1;
5892 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005893 else if (!strcmp(args[1], "type")) {
5894 int cur_arg;
5895 cur_arg = 2;
5896 if (!*args[cur_arg]) {
5897 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5898 file, linenum, args[0]);
5899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
5902 while (*(args[cur_arg])) {
5903 comp_append_type(comp, args[cur_arg]);
5904 cur_arg ++;
5905 continue;
5906 }
5907 }
5908 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005909 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005910 file, linenum, args[0]);
5911 err_code |= ERR_ALERT | ERR_FATAL;
5912 goto out;
5913 }
5914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005916 struct cfg_kw_list *kwl;
5917 int index;
5918
5919 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5920 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5921 if (kwl->kw[index].section != CFG_LISTEN)
5922 continue;
5923 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5924 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005925 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005926 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005927 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005930 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005931 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005932 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005933 err_code |= ERR_WARN;
5934 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005935 }
Willy Tarreau93893792009-07-23 13:19:11 +02005936 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005937 }
5938 }
5939 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005940
Willy Tarreau6daf3432008-01-22 16:44:08 +01005941 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005942 err_code |= ERR_ALERT | ERR_FATAL;
5943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 }
Willy Tarreau93893792009-07-23 13:19:11 +02005945 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005946 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005947 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948}
5949
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005950int
5951cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5952{
5953
5954 int err_code = 0;
5955 const char *err;
5956
5957 if (!strcmp(args[0], "userlist")) { /* new userlist */
5958 struct userlist *newul;
5959
5960 if (!*args[1]) {
5961 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5962 file, linenum, args[0]);
5963 err_code |= ERR_ALERT | ERR_FATAL;
5964 goto out;
5965 }
5966
5967 err = invalid_char(args[1]);
5968 if (err) {
5969 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5970 file, linenum, *err, args[0], args[1]);
5971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
5973 }
5974
5975 for (newul = userlist; newul; newul = newul->next)
5976 if (!strcmp(newul->name, args[1])) {
5977 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5978 file, linenum, args[1]);
5979 err_code |= ERR_WARN;
5980 goto out;
5981 }
5982
5983 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5984 if (!newul) {
5985 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5986 err_code |= ERR_ALERT | ERR_ABORT;
5987 goto out;
5988 }
5989
5990 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5991 newul->name = strdup(args[1]);
5992
5993 if (!newul->groupusers | !newul->name) {
5994 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5995 err_code |= ERR_ALERT | ERR_ABORT;
5996 goto out;
5997 }
5998
5999 newul->next = userlist;
6000 userlist = newul;
6001
6002 } else if (!strcmp(args[0], "group")) { /* new group */
6003 int cur_arg, i;
6004 const char *err;
6005
6006 if (!*args[1]) {
6007 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6008 file, linenum, args[0]);
6009 err_code |= ERR_ALERT | ERR_FATAL;
6010 goto out;
6011 }
6012
6013 err = invalid_char(args[1]);
6014 if (err) {
6015 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6016 file, linenum, *err, args[0], args[1]);
6017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
6019 }
6020
6021 for(i = 0; i < userlist->grpcnt; i++)
6022 if (!strcmp(userlist->groups[i], args[1])) {
6023 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6024 file, linenum, args[1], userlist->name);
6025 err_code |= ERR_ALERT;
6026 goto out;
6027 }
6028
6029 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6030 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6031 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6032 err_code |= ERR_ALERT | ERR_FATAL;
6033 goto out;
6034 }
6035
6036 cur_arg = 2;
6037
6038 while (*args[cur_arg]) {
6039 if (!strcmp(args[cur_arg], "users")) {
6040 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6041 cur_arg += 2;
6042 continue;
6043 } else {
6044 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6045 file, linenum, args[0]);
6046 err_code |= ERR_ALERT | ERR_FATAL;
6047 goto out;
6048 }
6049 }
6050
6051 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6052 } else if (!strcmp(args[0], "user")) { /* new user */
6053 struct auth_users *newuser;
6054 int cur_arg;
6055
6056 if (!*args[1]) {
6057 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6058 file, linenum, args[0]);
6059 err_code |= ERR_ALERT | ERR_FATAL;
6060 goto out;
6061 }
6062
6063 for (newuser = userlist->users; newuser; newuser = newuser->next)
6064 if (!strcmp(newuser->user, args[1])) {
6065 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6066 file, linenum, args[1], userlist->name);
6067 err_code |= ERR_ALERT;
6068 goto out;
6069 }
6070
6071 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6072 if (!newuser) {
6073 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6074 err_code |= ERR_ALERT | ERR_ABORT;
6075 goto out;
6076 }
6077
6078 newuser->user = strdup(args[1]);
6079
6080 newuser->next = userlist->users;
6081 userlist->users = newuser;
6082
6083 cur_arg = 2;
6084
6085 while (*args[cur_arg]) {
6086 if (!strcmp(args[cur_arg], "password")) {
6087#ifndef CONFIG_HAP_CRYPT
6088 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6089 file, linenum);
6090 err_code |= ERR_ALERT;
6091#endif
6092 newuser->pass = strdup(args[cur_arg + 1]);
6093 cur_arg += 2;
6094 continue;
6095 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6096 newuser->pass = strdup(args[cur_arg + 1]);
6097 newuser->flags |= AU_O_INSECURE;
6098 cur_arg += 2;
6099 continue;
6100 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006101 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006102 cur_arg += 2;
6103 continue;
6104 } else {
6105 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6106 file, linenum, args[0]);
6107 err_code |= ERR_ALERT | ERR_FATAL;
6108 goto out;
6109 }
6110 }
6111 } else {
6112 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6113 err_code |= ERR_ALERT | ERR_FATAL;
6114 }
6115
6116out:
6117 return err_code;
6118}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119
6120/*
6121 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006122 * Returns the error code, 0 if OK, or any combination of :
6123 * - ERR_ABORT: must abort ASAP
6124 * - ERR_FATAL: we can continue parsing but not start the service
6125 * - ERR_WARN: a warning has been emitted
6126 * - ERR_ALERT: an alert has been emitted
6127 * Only the two first ones can stop processing, the two others are just
6128 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006129 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006130int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006132 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006133 FILE *f;
6134 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006136 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006137
Willy Tarreaubaaee002006-06-26 02:48:02 +02006138 if ((f=fopen(file,"r")) == NULL)
6139 return -1;
6140
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006141 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006142 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006143 char *end;
6144 char *args[MAX_LINE_ARGS + 1];
6145 char *line = thisline;
6146
Willy Tarreaubaaee002006-06-26 02:48:02 +02006147 linenum++;
6148
6149 end = line + strlen(line);
6150
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006151 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6152 /* Check if we reached the limit and the last char is not \n.
6153 * Watch out for the last line without the terminating '\n'!
6154 */
6155 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006156 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006157 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006158 }
6159
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006161 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 line++;
6163
6164 arg = 0;
6165 args[arg] = line;
6166
6167 while (*line && arg < MAX_LINE_ARGS) {
6168 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6169 * C equivalent value. Other combinations left unchanged (eg: \1).
6170 */
6171 if (*line == '\\') {
6172 int skip = 0;
6173 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6174 *line = line[1];
6175 skip = 1;
6176 }
6177 else if (line[1] == 'r') {
6178 *line = '\r';
6179 skip = 1;
6180 }
6181 else if (line[1] == 'n') {
6182 *line = '\n';
6183 skip = 1;
6184 }
6185 else if (line[1] == 't') {
6186 *line = '\t';
6187 skip = 1;
6188 }
6189 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006190 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006191 unsigned char hex1, hex2;
6192 hex1 = toupper(line[2]) - '0';
6193 hex2 = toupper(line[3]) - '0';
6194 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6195 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6196 *line = (hex1<<4) + hex2;
6197 skip = 3;
6198 }
6199 else {
6200 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006201 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202 }
6203 }
6204 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006205 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006206 end -= skip;
6207 }
6208 line++;
6209 }
6210 else if (*line == '#' || *line == '\n' || *line == '\r') {
6211 /* end of string, end of loop */
6212 *line = 0;
6213 break;
6214 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006215 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006217 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006218 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 line++;
6220 args[++arg] = line;
6221 }
6222 else {
6223 line++;
6224 }
6225 }
6226
6227 /* empty line */
6228 if (!**args)
6229 continue;
6230
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006231 if (*line) {
6232 /* we had to stop due to too many args.
6233 * Let's terminate the string, print the offending part then cut the
6234 * last arg.
6235 */
6236 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6237 line++;
6238 *line = '\0';
6239
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006240 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006241 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006242 err_code |= ERR_ALERT | ERR_FATAL;
6243 args[arg] = line;
6244 }
6245
Willy Tarreau540abe42007-05-02 20:50:16 +02006246 /* zero out remaining args and ensure that at least one entry
6247 * is zeroed out.
6248 */
6249 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006250 args[arg] = line;
6251 }
6252
Willy Tarreau3842f002009-06-14 11:39:52 +02006253 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006254 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006255 char *tmp;
6256
Willy Tarreau3842f002009-06-14 11:39:52 +02006257 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006258 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006259 for (arg=0; *args[arg+1]; arg++)
6260 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006261 *tmp = '\0'; // fix the next arg to \0
6262 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006263 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006264 else if (!strcmp(args[0], "default")) {
6265 kwm = KWM_DEF;
6266 for (arg=0; *args[arg+1]; arg++)
6267 args[arg] = args[arg+1]; // shift args after inversion
6268 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006269
William Lallemand0f99e342011-10-12 17:50:54 +02006270 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6271 strcmp(args[0], "log") != 0) {
6272 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006273 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006274 }
6275
Willy Tarreau977b8e42006-12-29 14:19:17 +01006276 if (!strcmp(args[0], "listen") ||
6277 !strcmp(args[0], "frontend") ||
6278 !strcmp(args[0], "backend") ||
6279 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006280 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006281 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006282 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006283 cursection = strdup(args[0]);
6284 }
6285 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006287 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006288 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006289 }
6290 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006291 confsect = CFG_USERLIST;
6292 free(cursection);
6293 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006294 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006295 else if (!strcmp(args[0], "peers")) {
6296 confsect = CFG_PEERS;
6297 free(cursection);
6298 cursection = strdup(args[0]);
6299 }
6300
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 /* else it's a section keyword */
6302
6303 switch (confsect) {
6304 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006305 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 break;
6307 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006308 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006310 case CFG_USERLIST:
6311 err_code |= cfg_parse_users(file, linenum, args, kwm);
6312 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006313 case CFG_PEERS:
6314 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6315 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006317 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006318 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006320
6321 if (err_code & ERR_ABORT)
6322 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006324 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006325 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006327 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006328}
6329
Willy Tarreaubb925012009-07-23 13:36:36 +02006330/*
6331 * Returns the error code, 0 if OK, or any combination of :
6332 * - ERR_ABORT: must abort ASAP
6333 * - ERR_FATAL: we can continue parsing but not start the service
6334 * - ERR_WARN: a warning has been emitted
6335 * - ERR_ALERT: an alert has been emitted
6336 * Only the two first ones can stop processing, the two others are just
6337 * indicators.
6338 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006339int check_config_validity()
6340{
6341 int cfgerr = 0;
6342 struct proxy *curproxy = NULL;
6343 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006344 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006345 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006346 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006347 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006349 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 /*
6351 * Now, check for the integrity of all that we have collected.
6352 */
6353
6354 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006355 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356
Willy Tarreau193b8c62012-11-22 00:17:38 +01006357 if (!global.tune.max_http_hdr)
6358 global.tune.max_http_hdr = MAX_HTTP_HDR;
6359
6360 if (!global.tune.cookie_len)
6361 global.tune.cookie_len = CAPTURE_LEN;
6362
6363 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6364
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006365 /* first, we will invert the proxy list order */
6366 curproxy = NULL;
6367 while (proxy) {
6368 struct proxy *next;
6369
6370 next = proxy->next;
6371 proxy->next = curproxy;
6372 curproxy = proxy;
6373 if (!next)
6374 break;
6375 proxy = next;
6376 }
6377
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006379 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006380 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006381 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006382 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006383 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006384 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006385 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006386
Willy Tarreau050536d2012-10-04 08:47:34 +02006387 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006388 /* proxy ID not set, use automatic numbering with first
6389 * spare entry starting with next_pxid.
6390 */
6391 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6392 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6393 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006394 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006395 next_pxid++;
6396
Willy Tarreau55ea7572007-06-17 19:56:27 +02006397
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006399 /* ensure we don't keep listeners uselessly bound */
6400 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 curproxy = curproxy->next;
6402 continue;
6403 }
6404
Willy Tarreau16a21472012-11-19 12:39:59 +01006405 /* number of processes this proxy is bound to */
6406 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6407
Willy Tarreauff01a212009-03-15 13:46:16 +01006408 switch (curproxy->mode) {
6409 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006410 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006411 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006412 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6413 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006414 cfgerr++;
6415 }
6416
6417 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006418 Warning("config : servers will be ignored for %s '%s'.\n",
6419 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006420 break;
6421
6422 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006423 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006424 break;
6425
6426 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006427 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006428 break;
6429 }
6430
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006431 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006432 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006433 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006434 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6435 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006436 cfgerr++;
6437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006439 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006440 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6441 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006442 cfgerr++;
6443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006445 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006446 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6447 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006448 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006449 }
6450 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006451 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006452 /* If no LB algo is set in a backend, and we're not in
6453 * transparent mode, dispatch mode nor proxy mode, we
6454 * want to use balance roundrobin by default.
6455 */
6456 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6457 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 }
6459 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006460
Willy Tarreau1620ec32011-08-06 17:05:02 +02006461 if (curproxy->options & PR_O_DISPATCH)
6462 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6463 else if (curproxy->options & PR_O_HTTP_PROXY)
6464 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6465 else if (curproxy->options & PR_O_TRANSP)
6466 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006467
Willy Tarreau1620ec32011-08-06 17:05:02 +02006468 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6469 if (curproxy->options & PR_O_DISABLE404) {
6470 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6471 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6472 err_code |= ERR_WARN;
6473 curproxy->options &= ~PR_O_DISABLE404;
6474 }
6475 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6476 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6477 "send-state", proxy_type_str(curproxy), curproxy->id);
6478 err_code |= ERR_WARN;
6479 curproxy->options &= ~PR_O2_CHK_SNDST;
6480 }
Willy Tarreauef781042010-01-27 11:53:01 +01006481 }
6482
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006483 /* if a default backend was specified, let's find it */
6484 if (curproxy->defbe.name) {
6485 struct proxy *target;
6486
Alex Williams96532db2009-11-01 21:27:13 -05006487 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006488 if (!target) {
6489 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6490 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006491 cfgerr++;
6492 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006493 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6494 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006495 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006496 } else {
6497 free(curproxy->defbe.name);
6498 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006499 /* we force the backend to be present on at least all of
6500 * the frontend's processes.
6501 */
6502 target->bind_proc = curproxy->bind_proc ?
6503 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006504
6505 /* Emit a warning if this proxy also has some servers */
6506 if (curproxy->srv) {
6507 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6508 curproxy->id);
6509 err_code |= ERR_WARN;
6510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512 }
6513
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006514 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006515 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6516 /* map jump target for ACT_SETBE in req_rep chain */
6517 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006518 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006519 struct proxy *target;
6520
Willy Tarreaua496b602006-12-17 23:15:24 +01006521 if (exp->action != ACT_SETBE)
6522 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006523
Alex Williams96532db2009-11-01 21:27:13 -05006524 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006525 if (!target) {
6526 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6527 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006528 cfgerr++;
6529 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006530 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6531 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006532 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006533 } else {
6534 free((void *)exp->replace);
6535 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006536 /* we force the backend to be present on at least all of
6537 * the frontend's processes.
6538 */
6539 target->bind_proc = curproxy->bind_proc ?
6540 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006541 }
6542 }
6543 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006544
6545 /* find the target proxy for 'use_backend' rules */
6546 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006547 struct proxy *target;
6548
Alex Williams96532db2009-11-01 21:27:13 -05006549 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006550
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006551 if (!target) {
6552 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6553 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006554 cfgerr++;
6555 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006556 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6557 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006558 cfgerr++;
6559 } else {
6560 free((void *)rule->be.name);
6561 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006562 /* we force the backend to be present on at least all of
6563 * the frontend's processes.
6564 */
6565 target->bind_proc = curproxy->bind_proc ?
6566 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006567 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006568 }
6569
6570 /* find the target proxy for 'use_backend' rules */
6571 list_for_each_entry(srule, &curproxy->server_rules, list) {
6572 struct server *target = findserver(curproxy, srule->srv.name);
6573
6574 if (!target) {
6575 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6576 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6577 cfgerr++;
6578 continue;
6579 }
6580 free((void *)srule->srv.name);
6581 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006582 }
6583
Emeric Brunb982a3d2010-01-04 15:45:53 +01006584 /* find the target table for 'stick' rules */
6585 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6586 struct proxy *target;
6587
Emeric Brun1d33b292010-01-04 15:47:17 +01006588 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6589 if (mrule->flags & STK_IS_STORE)
6590 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6591
Emeric Brunb982a3d2010-01-04 15:45:53 +01006592 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006593 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006594 else
6595 target = curproxy;
6596
6597 if (!target) {
6598 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6599 curproxy->id, mrule->table.name);
6600 cfgerr++;
6601 }
6602 else if (target->table.size == 0) {
6603 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6604 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6605 cfgerr++;
6606 }
Willy Tarreau12785782012-04-27 21:37:17 +02006607 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6608 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006609 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6610 cfgerr++;
6611 }
6612 else {
6613 free((void *)mrule->table.name);
6614 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006615 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006616 }
6617 }
6618
6619 /* find the target table for 'store response' rules */
6620 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6621 struct proxy *target;
6622
Emeric Brun1d33b292010-01-04 15:47:17 +01006623 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6624
Emeric Brunb982a3d2010-01-04 15:45:53 +01006625 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006626 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006627 else
6628 target = curproxy;
6629
6630 if (!target) {
6631 Alert("Proxy '%s': unable to find store table '%s'.\n",
6632 curproxy->id, mrule->table.name);
6633 cfgerr++;
6634 }
6635 else if (target->table.size == 0) {
6636 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6637 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6638 cfgerr++;
6639 }
Willy Tarreau12785782012-04-27 21:37:17 +02006640 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6641 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006642 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6643 cfgerr++;
6644 }
6645 else {
6646 free((void *)mrule->table.name);
6647 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006648 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006649 }
6650 }
6651
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006652 /* find the target table for 'tcp-request' layer 4 rules */
6653 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6654 struct proxy *target;
6655
Willy Tarreaub4c84932013-07-23 19:15:30 +02006656 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006657 continue;
6658
6659 if (trule->act_prm.trk_ctr.table.n)
6660 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6661 else
6662 target = curproxy;
6663
6664 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006665 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6666 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006667 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006668 cfgerr++;
6669 }
6670 else if (target->table.size == 0) {
6671 Alert("Proxy '%s': table '%s' used but not configured.\n",
6672 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6673 cfgerr++;
6674 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006675 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6676 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6677 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006678 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006679 cfgerr++;
6680 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006681 else {
6682 free(trule->act_prm.trk_ctr.table.n);
6683 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006684 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006685 * to pass a list of counters to track and allocate them right here using
6686 * stktable_alloc_data_type().
6687 */
6688 }
6689 }
6690
Willy Tarreaud1f96522010-08-03 19:34:32 +02006691 /* find the target table for 'tcp-request' layer 6 rules */
6692 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6693 struct proxy *target;
6694
Willy Tarreaub4c84932013-07-23 19:15:30 +02006695 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006696 continue;
6697
6698 if (trule->act_prm.trk_ctr.table.n)
6699 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6700 else
6701 target = curproxy;
6702
6703 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006704 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6705 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006706 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006707 cfgerr++;
6708 }
6709 else if (target->table.size == 0) {
6710 Alert("Proxy '%s': table '%s' used but not configured.\n",
6711 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6712 cfgerr++;
6713 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006714 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6715 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6716 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006717 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006718 cfgerr++;
6719 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006720 else {
6721 free(trule->act_prm.trk_ctr.table.n);
6722 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006723 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006724 * to pass a list of counters to track and allocate them right here using
6725 * stktable_alloc_data_type().
6726 */
6727 }
6728 }
6729
Emeric Brun32da3c42010-09-23 18:39:19 +02006730 if (curproxy->table.peers.name) {
6731 struct peers *curpeers = peers;
6732
6733 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6734 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6735 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006736 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006737 break;
6738 }
6739 }
6740
6741 if (!curpeers) {
6742 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6743 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006744 free((void *)curproxy->table.peers.name);
6745 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006746 cfgerr++;
6747 }
6748 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006749 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6750 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006751 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006752 cfgerr++;
6753 }
6754 }
6755
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006756 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006757 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006758 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6759 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6760 "proxy", curproxy->id);
6761 cfgerr++;
6762 goto out_uri_auth_compat;
6763 }
6764
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006765 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006766 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006767 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006768 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006769
Willy Tarreau95fa4692010-02-01 13:05:50 +01006770 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6771 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006772
6773 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006774 uri_auth_compat_req[i++] = "realm";
6775 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6776 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006777
Willy Tarreau95fa4692010-02-01 13:05:50 +01006778 uri_auth_compat_req[i++] = "unless";
6779 uri_auth_compat_req[i++] = "{";
6780 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6781 uri_auth_compat_req[i++] = "}";
6782 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006783
Willy Tarreauff011f22011-01-06 17:51:27 +01006784 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6785 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006786 cfgerr++;
6787 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006788 }
6789
Willy Tarreauff011f22011-01-06 17:51:27 +01006790 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006791
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006792 if (curproxy->uri_auth->auth_realm) {
6793 free(curproxy->uri_auth->auth_realm);
6794 curproxy->uri_auth->auth_realm = NULL;
6795 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006796
6797 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006798 }
6799out_uri_auth_compat:
6800
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006801 /* compile the log format */
6802 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006803 if (curproxy->conf.logformat_string != default_http_log_format &&
6804 curproxy->conf.logformat_string != default_tcp_log_format &&
6805 curproxy->conf.logformat_string != clf_http_log_format)
6806 free(curproxy->conf.logformat_string);
6807 curproxy->conf.logformat_string = NULL;
6808 free(curproxy->conf.lfs_file);
6809 curproxy->conf.lfs_file = NULL;
6810 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006811 }
6812
Willy Tarreau62a61232013-04-12 18:13:46 +02006813 if (curproxy->conf.logformat_string) {
6814 curproxy->conf.args.ctx = ARGC_LOG;
6815 curproxy->conf.args.file = curproxy->conf.lfs_file;
6816 curproxy->conf.args.line = curproxy->conf.lfs_line;
6817 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006818 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006819 curproxy->conf.args.file = NULL;
6820 curproxy->conf.args.line = 0;
6821 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006822
Willy Tarreau62a61232013-04-12 18:13:46 +02006823 if (curproxy->conf.uniqueid_format_string) {
6824 curproxy->conf.args.ctx = ARGC_UIF;
6825 curproxy->conf.args.file = curproxy->conf.uif_file;
6826 curproxy->conf.args.line = curproxy->conf.uif_line;
6827 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006828 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006829 curproxy->conf.args.file = NULL;
6830 curproxy->conf.args.line = 0;
6831 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006832
6833 /* only now we can check if some args remain unresolved */
6834 cfgerr += smp_resolve_args(curproxy);
6835 if (!cfgerr)
6836 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006837
Willy Tarreau2738a142006-07-08 17:28:09 +02006838 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006839 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006840 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006841 (!curproxy->timeout.connect ||
6842 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006843 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006844 " | While not properly invalid, you will certainly encounter various problems\n"
6845 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006846 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006847 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006848 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006849 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006850
Willy Tarreau1fa31262007-12-03 00:36:16 +01006851 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6852 * We must still support older configurations, so let's find out whether those
6853 * parameters have been set or must be copied from contimeouts.
6854 */
6855 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006856 if (!curproxy->timeout.tarpit ||
6857 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006858 /* tarpit timeout not set. We search in the following order:
6859 * default.tarpit, curr.connect, default.connect.
6860 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006861 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006862 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006863 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006864 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006865 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006866 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006867 }
6868 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006869 (!curproxy->timeout.queue ||
6870 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006871 /* queue timeout not set. We search in the following order:
6872 * default.queue, curr.connect, default.connect.
6873 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006874 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006875 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006876 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006877 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006878 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006879 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006880 }
6881 }
6882
Willy Tarreau1620ec32011-08-06 17:05:02 +02006883 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006884 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6885 curproxy->check_req = (char *)malloc(curproxy->check_len);
6886 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006887 }
6888
Willy Tarreau193b8c62012-11-22 00:17:38 +01006889 /* ensure that cookie capture length is not too large */
6890 if (curproxy->capture_len >= global.tune.cookie_len) {
6891 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6892 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6893 err_code |= ERR_WARN;
6894 curproxy->capture_len = global.tune.cookie_len - 1;
6895 }
6896
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006897 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006898 if (curproxy->nb_req_cap) {
6899 if (curproxy->mode == PR_MODE_HTTP) {
6900 curproxy->req_cap_pool = create_pool("ptrcap",
6901 curproxy->nb_req_cap * sizeof(char *),
6902 MEM_F_SHARED);
6903 } else {
6904 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6905 proxy_type_str(curproxy), curproxy->id);
6906 err_code |= ERR_WARN;
6907 curproxy->to_log &= ~LW_REQHDR;
6908 curproxy->nb_req_cap = 0;
6909 }
6910 }
6911
6912 if (curproxy->nb_rsp_cap) {
6913 if (curproxy->mode == PR_MODE_HTTP) {
6914 curproxy->rsp_cap_pool = create_pool("ptrcap",
6915 curproxy->nb_rsp_cap * sizeof(char *),
6916 MEM_F_SHARED);
6917 } else {
6918 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6919 proxy_type_str(curproxy), curproxy->id);
6920 err_code |= ERR_WARN;
6921 curproxy->to_log &= ~LW_REQHDR;
6922 curproxy->nb_rsp_cap = 0;
6923 }
6924 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006925
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926 /* first, we will invert the servers list order */
6927 newsrv = NULL;
6928 while (curproxy->srv) {
6929 struct server *next;
6930
6931 next = curproxy->srv->next;
6932 curproxy->srv->next = newsrv;
6933 newsrv = curproxy->srv;
6934 if (!next)
6935 break;
6936 curproxy->srv = next;
6937 }
6938
Willy Tarreaudd701652010-05-25 23:03:02 +02006939 /* assign automatic UIDs to servers which don't have one yet */
6940 next_id = 1;
6941 newsrv = curproxy->srv;
6942 while (newsrv != NULL) {
6943 if (!newsrv->puid) {
6944 /* server ID not set, use automatic numbering with first
6945 * spare entry starting with next_svid.
6946 */
6947 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6948 newsrv->conf.id.key = newsrv->puid = next_id;
6949 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6950 }
6951 next_id++;
6952 newsrv = newsrv->next;
6953 }
6954
Willy Tarreau20697042007-11-15 23:26:18 +01006955 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006956 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006957
Willy Tarreau62c3be22012-01-20 13:12:32 +01006958 /*
6959 * If this server supports a maxconn parameter, it needs a dedicated
6960 * tasks to fill the emptied slots when a connection leaves.
6961 * Also, resolve deferred tracking dependency if needed.
6962 */
6963 newsrv = curproxy->srv;
6964 while (newsrv != NULL) {
6965 if (newsrv->minconn > newsrv->maxconn) {
6966 /* Only 'minconn' was specified, or it was higher than or equal
6967 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6968 * this will avoid further useless expensive computations.
6969 */
6970 newsrv->maxconn = newsrv->minconn;
6971 } else if (newsrv->maxconn && !newsrv->minconn) {
6972 /* minconn was not specified, so we set it to maxconn */
6973 newsrv->minconn = newsrv->maxconn;
6974 }
6975
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006976#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006977 if (newsrv->use_ssl || newsrv->check.use_ssl)
6978 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006979#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006980
Willy Tarreau2f075e92013-12-03 11:11:34 +01006981 /* set the check type on the server */
6982 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6983
Willy Tarreau62c3be22012-01-20 13:12:32 +01006984 if (newsrv->trackit) {
6985 struct proxy *px;
6986 struct server *srv;
6987 char *pname, *sname;
6988
6989 pname = newsrv->trackit;
6990 sname = strrchr(pname, '/');
6991
6992 if (sname)
6993 *sname++ = '\0';
6994 else {
6995 sname = pname;
6996 pname = NULL;
6997 }
6998
6999 if (pname) {
7000 px = findproxy(pname, PR_CAP_BE);
7001 if (!px) {
7002 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7003 proxy_type_str(curproxy), curproxy->id,
7004 newsrv->id, pname);
7005 cfgerr++;
7006 goto next_srv;
7007 }
7008 } else
7009 px = curproxy;
7010
7011 srv = findserver(px, sname);
7012 if (!srv) {
7013 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7014 proxy_type_str(curproxy), curproxy->id,
7015 newsrv->id, sname);
7016 cfgerr++;
7017 goto next_srv;
7018 }
7019
Willy Tarreauff5ae352013-12-11 20:36:34 +01007020 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007021 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7022 "tracking as it does not have checks enabled.\n",
7023 proxy_type_str(curproxy), curproxy->id,
7024 newsrv->id, px->id, srv->id);
7025 cfgerr++;
7026 goto next_srv;
7027 }
7028
7029 if (curproxy != px &&
7030 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7031 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7032 "tracking: disable-on-404 option inconsistency.\n",
7033 proxy_type_str(curproxy), curproxy->id,
7034 newsrv->id, px->id, srv->id);
7035 cfgerr++;
7036 goto next_srv;
7037 }
7038
7039 /* if the other server is forced disabled, we have to do the same here */
7040 if (srv->state & SRV_MAINTAIN) {
7041 newsrv->state |= SRV_MAINTAIN;
Willy Tarreau33a08db2013-12-11 21:03:31 +01007042 newsrv->check.state |= CHK_ST_PAUSED;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007043 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007044 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007045 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007046 }
7047
7048 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007049 newsrv->tracknext = srv->trackers;
7050 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007051
7052 free(newsrv->trackit);
7053 newsrv->trackit = NULL;
7054 }
7055 next_srv:
7056 newsrv = newsrv->next;
7057 }
7058
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007059 /* We have to initialize the server lookup mechanism depending
7060 * on what LB algorithm was choosen.
7061 */
7062
7063 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7064 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7065 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007066 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7067 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7068 init_server_map(curproxy);
7069 } else {
7070 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7071 fwrr_init_server_groups(curproxy);
7072 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007073 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007074
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007075 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007076 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7077 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7078 fwlc_init_server_tree(curproxy);
7079 } else {
7080 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7081 fas_init_server_tree(curproxy);
7082 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007083 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007084
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007085 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007086 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7087 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7088 chash_init_server_tree(curproxy);
7089 } else {
7090 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7091 init_server_map(curproxy);
7092 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007093 break;
7094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095
7096 if (curproxy->options & PR_O_LOGASAP)
7097 curproxy->to_log &= ~LW_BYTES;
7098
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007099 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007100 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007101 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7102 proxy_type_str(curproxy), curproxy->id);
7103 err_code |= ERR_WARN;
7104 }
7105
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007106 if (curproxy->mode != PR_MODE_HTTP) {
7107 int optnum;
7108
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007109 if (curproxy->uri_auth) {
7110 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7111 proxy_type_str(curproxy), curproxy->id);
7112 err_code |= ERR_WARN;
7113 curproxy->uri_auth = NULL;
7114 }
7115
Willy Tarreau87cf5142011-08-19 22:57:24 +02007116 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007117 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7118 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7119 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007120 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007121 }
7122
7123 if (curproxy->options & PR_O_ORGTO) {
7124 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7125 "originalto", proxy_type_str(curproxy), curproxy->id);
7126 err_code |= ERR_WARN;
7127 curproxy->options &= ~PR_O_ORGTO;
7128 }
7129
7130 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7131 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7132 (curproxy->cap & cfg_opts[optnum].cap) &&
7133 (curproxy->options & cfg_opts[optnum].val)) {
7134 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7135 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7136 err_code |= ERR_WARN;
7137 curproxy->options &= ~cfg_opts[optnum].val;
7138 }
7139 }
7140
7141 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7142 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7143 (curproxy->cap & cfg_opts2[optnum].cap) &&
7144 (curproxy->options2 & cfg_opts2[optnum].val)) {
7145 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7146 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7147 err_code |= ERR_WARN;
7148 curproxy->options2 &= ~cfg_opts2[optnum].val;
7149 }
7150 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007151
Pieter Baauwd551fb52013-05-08 22:49:23 +02007152#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007153 if (curproxy->conn_src.bind_hdr_occ) {
7154 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007155 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007156 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007157 err_code |= ERR_WARN;
7158 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007160 }
7161
Willy Tarreaubaaee002006-06-26 02:48:02 +02007162 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007163 * ensure that we're not cross-dressing a TCP server into HTTP.
7164 */
7165 newsrv = curproxy->srv;
7166 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007167 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007168 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7169 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007170 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007171 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007172
Willy Tarreau0cec3312011-10-31 13:49:26 +01007173 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7174 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7175 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7176 err_code |= ERR_WARN;
7177 }
7178
Willy Tarreau82ffa392013-08-13 17:19:08 +02007179 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7180 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7181 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7182 err_code |= ERR_WARN;
7183 }
7184
Pieter Baauwd551fb52013-05-08 22:49:23 +02007185#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007186 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7187 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007188 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 +01007189 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007190 err_code |= ERR_WARN;
7191 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007192#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007193 newsrv = newsrv->next;
7194 }
7195
Willy Tarreauc1a21672009-08-16 22:37:44 +02007196 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007197 if (!curproxy->accept)
7198 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007199
Willy Tarreauc1a21672009-08-16 22:37:44 +02007200 if (curproxy->tcp_req.inspect_delay ||
7201 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007202 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007203
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007204 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007205 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007206 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007207 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007208
7209 /* both TCP and HTTP must check switching rules */
7210 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7211 }
7212
7213 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007214 if (curproxy->tcp_req.inspect_delay ||
7215 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7216 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7217
Emeric Brun97679e72010-09-23 17:56:44 +02007218 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7219 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7220
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007221 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007222 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007223 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007224 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007225
7226 /* If the backend does requires RDP cookie persistence, we have to
7227 * enable the corresponding analyser.
7228 */
7229 if (curproxy->options2 & PR_O2_RDPC_PRST)
7230 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7231 }
7232
Emeric Brunc52962f2012-11-15 18:28:02 +01007233#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007234 /* Configure SSL for each bind line.
7235 * Note: if configuration fails at some point, the ->ctx member
7236 * remains NULL so that listeners can later detach.
7237 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007238 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007239 if (!bind_conf->is_ssl) {
7240 if (bind_conf->default_ctx) {
7241 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7242 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7243 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007244 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007245 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007246 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007247 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007248 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007249 cfgerr++;
7250 continue;
7251 }
7252
Emeric Brun4b3091e2012-09-24 15:48:52 +02007253 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007254 Alert("Unable to allocate SSL session cache.\n");
7255 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007256 continue;
7257 }
7258
Emeric Brunfc0421f2012-09-07 17:30:07 +02007259 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007260 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007261 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007262#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007263
Willy Tarreaue6b98942007-10-29 01:09:36 +01007264 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007265 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007266 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007267 if (!listener->luid) {
7268 /* listener ID not set, use automatic numbering with first
7269 * spare entry starting with next_luid.
7270 */
7271 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7272 listener->conf.id.key = listener->luid = next_id;
7273 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007274 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007275 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007276
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007277 /* enable separate counters */
7278 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7279 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007280 if (!listener->name)
7281 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007282 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007283
Willy Tarreaue6b98942007-10-29 01:09:36 +01007284 if (curproxy->options & PR_O_TCP_NOLING)
7285 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007286 if (!listener->maxconn)
7287 listener->maxconn = curproxy->maxconn;
7288 if (!listener->backlog)
7289 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007290 if (!listener->maxaccept)
7291 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7292
7293 /* we want to have an optimal behaviour on single process mode to
7294 * maximize the work at once, but in multi-process we want to keep
7295 * some fairness between processes, so we target half of the max
7296 * number of events to be balanced over all the processes the proxy
7297 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7298 * used to disable the limit.
7299 */
7300 if (listener->maxaccept > 0) {
7301 if (nbproc > 1)
7302 listener->maxaccept = (listener->maxaccept + 1) / 2;
7303 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7304 }
7305
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007306 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007307 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007308 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007309 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007310
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007311 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7312 listener->options |= LI_O_TCP_RULES;
7313
Willy Tarreaude3041d2010-05-31 10:56:17 +02007314 if (curproxy->mon_mask.s_addr)
7315 listener->options |= LI_O_CHK_MONNET;
7316
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007317 /* smart accept mode is automatic in HTTP mode */
7318 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007319 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007320 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7321 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007322 }
7323
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007324 /* Release unused SSL configs */
7325 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7326 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007327 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007328#ifdef USE_OPENSSL
7329 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007330 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007331 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007332 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007333 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007334#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007335 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007336
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007337 /* Check multi-process mode compatibility for the current proxy */
7338 if (global.nbproc > 1) {
7339 int nbproc = 0;
7340 if (curproxy->bind_proc) {
7341 int proc;
7342 for (proc = 0; proc < global.nbproc; proc++) {
7343 if (curproxy->bind_proc & (1 << proc)) {
7344 nbproc++;
7345 }
7346 }
7347 } else {
7348 nbproc = global.nbproc;
7349 }
7350 if (curproxy->table.peers.name) {
7351 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7352 curproxy->id);
7353 cfgerr++;
7354 }
7355 if (nbproc > 1) {
7356 if (curproxy->uri_auth) {
7357 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7358 curproxy->id);
7359 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7360 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7361 curproxy->id);
7362 }
7363 }
7364 if (curproxy->appsession_name) {
7365 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7366 curproxy->id);
7367 }
7368 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7369 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7370 curproxy->id);
7371 }
7372 }
7373 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007374
7375 /* create the task associated with the proxy */
7376 curproxy->task = task_new();
7377 if (curproxy->task) {
7378 curproxy->task->context = curproxy;
7379 curproxy->task->process = manage_proxy;
7380 /* no need to queue, it will be done automatically if some
7381 * listener gets limited.
7382 */
7383 curproxy->task->expire = TICK_ETERNITY;
7384 } else {
7385 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7386 curproxy->id);
7387 cfgerr++;
7388 }
7389
Willy Tarreaubaaee002006-06-26 02:48:02 +02007390 curproxy = curproxy->next;
7391 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007392
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007393 /* Check multi-process mode compatibility */
7394 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007395 if (global.stats_fe && !global.stats_fe->bind_proc) {
7396 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 +01007397 }
7398 }
7399
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007400 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7401 struct auth_users *curuser;
7402 int g;
7403
7404 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7405 unsigned int group_mask = 0;
7406 char *group = NULL;
7407
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007408 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007409 continue;
7410
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007411 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007412
7413 for (g = 0; g < curuserlist->grpcnt; g++)
7414 if (!strcmp(curuserlist->groups[g], group))
7415 break;
7416
7417 if (g == curuserlist->grpcnt) {
7418 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7419 curuserlist->name, group, curuser->user);
7420 err_code |= ERR_ALERT | ERR_FATAL;
7421 goto out;
7422 }
7423
7424 group_mask |= (1 << g);
7425 }
7426
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007427 free(curuser->u.groups);
7428 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007429 }
7430
7431 for (g = 0; g < curuserlist->grpcnt; g++) {
7432 char *user = NULL;
7433
7434 if (!curuserlist->groupusers[g])
7435 continue;
7436
7437 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7438 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7439 if (!strcmp(curuser->user, user))
7440 break;
7441
7442 if (!curuser) {
7443 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7444 curuserlist->name, user, curuserlist->groups[g]);
7445 err_code |= ERR_ALERT | ERR_FATAL;
7446 goto out;
7447 }
7448
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007449 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007450 }
7451
7452 free(curuserlist->groupusers[g]);
7453 }
7454
7455 free(curuserlist->groupusers);
7456
7457#ifdef DEBUG_AUTH
7458 for (g = 0; g < curuserlist->grpcnt; g++) {
7459 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7460
7461 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007462 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007463 fprintf(stderr, " %s", curuser->user);
7464 }
7465
7466 fprintf(stderr, "\n");
7467 }
7468#endif
7469
Willy Tarreaufbb78422011-06-05 15:38:35 +02007470 }
7471
7472 /* automatically compute fullconn if not set. We must not do it in the
7473 * loop above because cross-references are not yet fully resolved.
7474 */
7475 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7476 /* If <fullconn> is not set, let's set it to 10% of the sum of
7477 * the possible incoming frontend's maxconns.
7478 */
7479 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7480 struct proxy *fe;
7481 int total = 0;
7482
7483 /* sum up the number of maxconns of frontends which
7484 * reference this backend at least once or which are
7485 * the same one ('listen').
7486 */
7487 for (fe = proxy; fe; fe = fe->next) {
7488 struct switching_rule *rule;
7489 struct hdr_exp *exp;
7490 int found = 0;
7491
7492 if (!(fe->cap & PR_CAP_FE))
7493 continue;
7494
7495 if (fe == curproxy) /* we're on a "listen" instance */
7496 found = 1;
7497
7498 if (fe->defbe.be == curproxy) /* "default_backend" */
7499 found = 1;
7500
7501 /* check if a "use_backend" rule matches */
7502 if (!found) {
7503 list_for_each_entry(rule, &fe->switching_rules, list) {
7504 if (rule->be.backend == curproxy) {
7505 found = 1;
7506 break;
7507 }
7508 }
7509 }
7510
7511 /* check if a "reqsetbe" rule matches */
7512 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7513 if (exp->action == ACT_SETBE &&
7514 (struct proxy *)exp->replace == curproxy) {
7515 found = 1;
7516 break;
7517 }
7518 }
7519
7520 /* now we've checked all possible ways to reference a backend
7521 * from a frontend.
7522 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007523 if (!found)
7524 continue;
7525 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007526 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007527 /* we have the sum of the maxconns in <total>. We only
7528 * keep 10% of that sum to set the default fullconn, with
7529 * a hard minimum of 1 (to avoid a divide by zero).
7530 */
7531 curproxy->fullconn = (total + 9) / 10;
7532 if (!curproxy->fullconn)
7533 curproxy->fullconn = 1;
7534 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007535 }
7536
Willy Tarreau056f5682010-06-06 15:51:11 +02007537 /* initialize stick-tables on backend capable proxies. This must not
7538 * be done earlier because the data size may be discovered while parsing
7539 * other proxies.
7540 */
Godbach9703e662013-12-11 21:11:41 +08007541 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7542 if (!stktable_init(&curproxy->table)) {
7543 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7544 cfgerr++;
7545 }
7546 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007547
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007548 /*
7549 * Recount currently required checks.
7550 */
7551
7552 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7553 int optnum;
7554
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007555 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7556 if (curproxy->options & cfg_opts[optnum].val)
7557 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007558
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007559 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7560 if (curproxy->options2 & cfg_opts2[optnum].val)
7561 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007562 }
7563
Willy Tarreau122541c2011-09-07 21:24:49 +02007564 if (peers) {
7565 struct peers *curpeers = peers, **last;
7566 struct peer *p, *pb;
7567
7568 /* Remove all peers sections which don't have a valid listener.
7569 * This can happen when a peers section is never referenced and
7570 * does not contain a local peer.
7571 */
7572 last = &peers;
7573 while (*last) {
7574 curpeers = *last;
7575 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007576 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007577 last = &curpeers->next;
7578 continue;
7579 }
7580
7581 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7582 curpeers->id, localpeer);
7583
7584 p = curpeers->remote;
7585 while (p) {
7586 pb = p->next;
7587 free(p->id);
7588 free(p);
7589 p = pb;
7590 }
7591
7592 /* Destroy and unlink this curpeers section.
7593 * Note: curpeers is backed up into *last.
7594 */
7595 free(curpeers->id);
7596 curpeers = curpeers->next;
7597 free(*last);
7598 *last = curpeers;
7599 }
7600 }
7601
Willy Tarreau34eb6712011-10-24 18:15:04 +02007602 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007603 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007604 MEM_F_SHARED);
7605
Willy Tarreaubb925012009-07-23 13:36:36 +02007606 if (cfgerr > 0)
7607 err_code |= ERR_ALERT | ERR_FATAL;
7608 out:
7609 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007610}
7611
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007612/*
7613 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7614 * parsing sessions.
7615 */
7616void cfg_register_keywords(struct cfg_kw_list *kwl)
7617{
7618 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7619}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007620
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007621/*
7622 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7623 */
7624void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7625{
7626 LIST_DEL(&kwl->list);
7627 LIST_INIT(&kwl->list);
7628}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007629
7630/*
7631 * Local variables:
7632 * c-indent-level: 8
7633 * c-basic-offset: 8
7634 * End:
7635 */