blob: 00b75828d9d71aded962cf319dc628aaca4d01c5 [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 Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100113/* permit to store configuration section */
114struct cfg_section {
115 struct list list;
116 char *section_name;
117 int (*section_parser)(const char *, int, char **, int);
118};
119
120/* Used to chain configuration sections definitions. This list
121 * stores struct cfg_section
122 */
123struct list sections = LIST_HEAD_INIT(sections);
124
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100126struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127 const char *name;
128 unsigned int val;
129 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100130 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100132};
133
134/* proxy->options */
135static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
138 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
139 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
140 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
141 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
142 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100144 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
146 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
147 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
148 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
149 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100150#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100152#else
153 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100154#endif
155
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100157};
158
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159/* proxy->options2 */
160static const struct cfg_opt cfg_opts2[] =
161{
162#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
165 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "splice-request", 0, 0, 0, 0 },
168 { "splice-response", 0, 0, 0, 0 },
169 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
172 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
173 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
174 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
175 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
176 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
177 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
178 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
179 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400180 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200182 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200183 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184 { NULL, 0, 0, 0 }
185};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186
Willy Tarreau6daf3432008-01-22 16:44:08 +0100187static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
189int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100190int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200192/* List head of all known configuration keywords */
193static struct cfg_kw_list cfg_keywords = {
194 .list = LIST_HEAD_INIT(cfg_keywords.list)
195};
196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197/*
198 * converts <str> to a list of listeners which are dynamically allocated.
199 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
200 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
201 * - <port> is a numerical port from 1 to 65535 ;
202 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
203 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200204 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
205 * not NULL, it must be a valid pointer to either NULL or a freeable area that
206 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200208int 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 +0200209{
210 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 int port, end;
213
214 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100218 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
220 str = next;
221 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100222 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 *next++ = 0;
224 }
225
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100226 ss2 = str2sa_range(str, &port, &end, err,
227 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
228 if (!ss2)
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100232 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200233 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100237 if (!port || !end) {
238 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
239 goto fail;
240 }
241
Emeric Bruned760922010-10-22 17:59:25 +0200242 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200244 goto fail;
245 }
246
247 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100252 else if (ss2->ss_family == AF_UNSPEC) {
253 socklen_t addr_len;
254
255 /* We want to attach to an already bound fd whose number
256 * is in the addr part of ss2 when cast to sockaddr_in.
257 * Note that by definition there is a single listener.
258 * We still have to determine the address family to
259 * register the correct protocol.
260 */
261 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
262 addr_len = sizeof(*ss2);
263 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
264 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
265 goto fail;
266 }
267
268 port = end = get_host_port(ss2);
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100271 /* OK the address looks correct */
272 ss = *ss2;
273
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 for (; port <= end; port++) {
275 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100276 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200277 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
278 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
279 l->frontend = curproxy;
280 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200284 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 l->state = LI_INIT;
286
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100287 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 tcpv4_add_listener(l);
290 }
Emeric Bruned760922010-10-22 17:59:25 +0200291 else if (ss.ss_family == AF_INET6) {
292 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
293 tcpv6_add_listener(l);
294 }
295 else {
Emeric Bruned760922010-10-22 17:59:25 +0200296 uxst_add_listener(l);
297 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200299 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 } /* end for(port) */
302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
Willy Tarreau61d18892009-03-31 10:49:21 +0200310/* Report a warning if a rule is placed after a 'block' rule.
311 * Return 1 if the warning has been emitted, otherwise 0.
312 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100313int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200314{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200315 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200316 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
317 file, line, arg);
318 return 1;
319 }
320 return 0;
321}
322
Willy Tarreau5002f572014-04-23 01:32:02 +0200323/* Report a warning if a rule is placed after an 'http_request' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
327{
328 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
Willy Tarreau61d18892009-03-31 10:49:21 +0200336/* Report a warning if a rule is placed after a reqrewrite rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
341 if (proxy->req_exp) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a reqadd rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100354 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a redirect rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a 'use_backend' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
Willy Tarreauee445d92014-04-23 01:39:04 +0200388/* Report a warning if a rule is placed after a 'use-server' rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
391int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
392{
393 if (!LIST_ISEMPTY(&proxy->server_rules)) {
394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
Willy Tarreau61d18892009-03-31 10:49:21 +0200401/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
Willy Tarreau5002f572014-04-23 01:32:02 +0200404 return warnif_rule_after_http_req(proxy, file, line, arg) ||
405 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
406 warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200408 warnif_rule_after_use_backend(proxy, file, line, arg) ||
409 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200410}
411
412/* report a warning if an http-request rule is dangerously placed */
413int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
414{
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200420}
421
422/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
425 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
426 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200427 warnif_rule_after_use_backend(proxy, file, line, arg) ||
428 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200429}
430
431/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100432int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200433{
434 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a redirect rule is dangerously placed */
440int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
443 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200444}
445
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446/* Report it if a request ACL condition uses some keywords that are incompatible
447 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
448 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
449 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100451static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100453 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200454 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100457 return 0;
458
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100459 acl = acl_cond_conflicts(cond, where);
460 if (acl) {
461 if (acl->name && *acl->name)
462 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
463 file, line, acl->name, sample_ckp_names(where));
464 else
465 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 +0200466 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100467 return ERR_WARN;
468 }
469 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100470 return 0;
471
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100472 if (acl->name && *acl->name)
473 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200474 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100475 else
476 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200477 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100478 return ERR_WARN;
479}
480
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 * parse a line in a <global> section. Returns the error code, 0 if OK, or
483 * any combination of :
484 * - ERR_ABORT: must abort ASAP
485 * - ERR_FATAL: we can continue parsing but not start the service
486 * - ERR_WARN: a warning has been emitted
487 * - ERR_ALERT: an alert has been emitted
488 * Only the two first ones can stop processing, the two others are just
489 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200491int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492{
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200494 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (!strcmp(args[0], "global")) { /* new section */
497 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200500 else if (!strcmp(args[0], "ca-base")) {
501#ifdef USE_OPENSSL
502 if (global.ca_base != NULL) {
503 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT;
505 goto out;
506 }
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 global.ca_base = strdup(args[1]);
513#else
514 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517#endif
518 }
519 else if (!strcmp(args[0], "crt-base")) {
520#ifdef USE_OPENSSL
521 if (global.crt_base != NULL) {
522 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT;
524 goto out;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 global.crt_base = strdup(args[1]);
532#else
533 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536#endif
537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "daemon")) {
539 global.mode |= MODE_DAEMON;
540 }
541 else if (!strcmp(args[0], "debug")) {
542 global.mode |= MODE_DEBUG;
543 }
544 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100545 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200547 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100548 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100551 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100553 else if (!strcmp(args[0], "nosplice")) {
554 global.tune.options &= ~GTUNE_USE_SPLICE;
555 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200556 else if (!strcmp(args[0], "nogetaddrinfo")) {
557 global.tune.options &= ~GTUNE_USE_GAI;
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 else if (!strcmp(args[0], "quiet")) {
560 global.mode |= MODE_QUIET;
561 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200562 else if (!strcmp(args[0], "tune.maxpollevents")) {
563 if (global.tune.maxpollevents != 0) {
564 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200565 err_code |= ERR_ALERT;
566 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200567 }
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 }
573 global.tune.maxpollevents = atol(args[1]);
574 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100575 else if (!strcmp(args[0], "tune.maxaccept")) {
576 if (global.tune.maxaccept != 0) {
577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100580 }
581 if (*(args[1]) == 0) {
582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 }
586 global.tune.maxaccept = atol(args[1]);
587 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200588 else if (!strcmp(args[0], "tune.chksize")) {
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.chksize = atol(args[1]);
595 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200596#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200597 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
598 global.tune.sslprivatecache = 1;
599 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100600 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.sslcachesize = atol(args[1]);
607 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100608 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
609 unsigned int ssllifetime;
610 const char *res;
611
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617
618 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
619 if (res) {
620 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
621 file, linenum, *res, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625
626 global.tune.ssllifetime = ssllifetime;
627 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100628 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.ssl_max_record = atol(args[1]);
635 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200636 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.ssl_default_dh_param = atol(args[1]);
643 if (global.tune.ssl_default_dh_param < 1024) {
644 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200650 else if (!strcmp(args[0], "tune.bufsize")) {
651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.bufsize = atol(args[1]);
657 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
658 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100659 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100660 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200661 }
662 else if (!strcmp(args[0], "tune.maxrewrite")) {
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668 global.tune.maxrewrite = atol(args[1]);
669 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
670 global.tune.maxrewrite = global.tune.bufsize / 2;
671 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100672 else if (!strcmp(args[0], "tune.idletimer")) {
673 unsigned int idle;
674 const char *res;
675
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681
682 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
683 if (res) {
684 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
685 file, linenum, *res, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689
690 if (idle > 65535) {
691 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.idle_timer = idle;
696 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100697 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
698 if (global.tune.client_rcvbuf != 0) {
699 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
700 err_code |= ERR_ALERT;
701 goto out;
702 }
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.client_rcvbuf = atol(args[1]);
709 }
710 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
711 if (global.tune.server_rcvbuf != 0) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT;
714 goto out;
715 }
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.tune.server_rcvbuf = atol(args[1]);
722 }
723 else if (!strcmp(args[0], "tune.sndbuf.client")) {
724 if (global.tune.client_sndbuf != 0) {
725 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT;
727 goto out;
728 }
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.client_sndbuf = atol(args[1]);
735 }
736 else if (!strcmp(args[0], "tune.sndbuf.server")) {
737 if (global.tune.server_sndbuf != 0) {
738 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT;
740 goto out;
741 }
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747 global.tune.server_sndbuf = atol(args[1]);
748 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200749 else if (!strcmp(args[0], "tune.pipesize")) {
750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.pipesize = atol(args[1]);
756 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100757 else if (!strcmp(args[0], "tune.http.cookielen")) {
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 global.tune.cookie_len = atol(args[1]) + 1;
764 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200765 else if (!strcmp(args[0], "tune.http.maxhdr")) {
766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 global.tune.max_http_hdr = atol(args[1]);
772 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100773 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
774#ifdef USE_ZLIB
775 if (*args[1]) {
776 global.tune.zlibmemlevel = atoi(args[1]);
777 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
778 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
779 file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 } else {
784 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
785 file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789#else
790 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
793#endif
794 }
795 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
796#ifdef USE_ZLIB
797 if (*args[1]) {
798 global.tune.zlibwindowsize = atoi(args[1]);
799 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
800 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
801 file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805 } else {
806 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
807 file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811#else
812 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815#endif
816 }
William Lallemandf3747832012-11-09 12:33:10 +0100817 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
818 if (*args[1]) {
819 global.tune.comp_maxlevel = atoi(args[1]);
820 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
821 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
822 file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 } else {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 else if (!strcmp(args[0], "uid")) {
834 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200835 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200836 err_code |= ERR_ALERT;
837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 }
839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 }
844 global.uid = atol(args[1]);
845 }
846 else if (!strcmp(args[0], "gid")) {
847 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200848 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200849 err_code |= ERR_ALERT;
850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 }
852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 }
857 global.gid = atol(args[1]);
858 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200859 /* user/group name handling */
860 else if (!strcmp(args[0], "user")) {
861 struct passwd *ha_user;
862 if (global.uid != 0) {
863 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 err_code |= ERR_ALERT;
865 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200866 }
867 errno = 0;
868 ha_user = getpwnam(args[1]);
869 if (ha_user != NULL) {
870 global.uid = (int)ha_user->pw_uid;
871 }
872 else {
873 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 +0200874 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200875 }
876 }
877 else if (!strcmp(args[0], "group")) {
878 struct group *ha_group;
879 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200880 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200881 err_code |= ERR_ALERT;
882 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200883 }
884 errno = 0;
885 ha_group = getgrnam(args[1]);
886 if (ha_group != NULL) {
887 global.gid = (int)ha_group->gr_gid;
888 }
889 else {
890 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 +0200891 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200892 }
893 }
894 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100902 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
903 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
904 file, linenum, args[0], LONGBITS, global.nbproc);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 else if (!strcmp(args[0], "maxconn")) {
910 if (global.maxconn != 0) {
911 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 }
915 if (*(args[1]) == 0) {
916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 }
920 global.maxconn = atol(args[1]);
921#ifdef SYSTEM_MAXCONN
922 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
923 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);
924 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927#endif /* SYSTEM_MAXCONN */
928 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200929 else if (!strcmp(args[0], "maxsslconn")) {
930#ifdef USE_OPENSSL
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.maxsslconn = atol(args[1]);
937#else
Emeric Brun0914df82012-10-02 18:45:42 +0200938 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200941#endif
942 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100943 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
944#ifdef USE_OPENSSL
945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
949 }
950 free(global.listen_default_ciphers);
951 global.listen_default_ciphers = strdup(args[1]);
952#else
953 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956#endif
957 }
958 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
959#ifdef USE_OPENSSL
960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 free(global.connect_default_ciphers);
966 global.connect_default_ciphers = strdup(args[1]);
967#else
968 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
971#endif
972 }
Emeric Brun850efd52014-01-29 12:24:34 +0100973 else if (!strcmp(args[0], "ssl-server-verify")) {
974 if (*(args[1]) == 0) {
975 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979 if (strcmp(args[1],"none") == 0)
980 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
981 else if (strcmp(args[1],"required") == 0)
982 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
983 else {
984 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200989 else if (!strcmp(args[0], "maxconnrate")) {
990 if (global.cps_lim != 0) {
991 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
992 err_code |= ERR_ALERT;
993 goto out;
994 }
995 if (*(args[1]) == 0) {
996 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 global.cps_lim = atol(args[1]);
1001 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001002 else if (!strcmp(args[0], "maxsessrate")) {
1003 if (global.sps_lim != 0) {
1004 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1005 err_code |= ERR_ALERT;
1006 goto out;
1007 }
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 global.sps_lim = atol(args[1]);
1014 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001015 else if (!strcmp(args[0], "maxsslrate")) {
1016 if (global.ssl_lim != 0) {
1017 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT;
1019 goto out;
1020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 global.ssl_lim = atol(args[1]);
1027 }
William Lallemandd85f9172012-11-09 17:05:39 +01001028 else if (!strcmp(args[0], "maxcomprate")) {
1029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034 global.comp_rate_lim = atoi(args[1]) * 1024;
1035 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001036 else if (!strcmp(args[0], "maxpipes")) {
1037 if (global.maxpipes != 0) {
1038 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT;
1040 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001041 }
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001046 }
1047 global.maxpipes = atol(args[1]);
1048 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001049 else if (!strcmp(args[0], "maxzlibmem")) {
1050 if (*(args[1]) == 0) {
1051 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
1054 }
William Lallemande3a7d992012-11-20 11:25:20 +01001055 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001056 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001057 else if (!strcmp(args[0], "maxcompcpuusage")) {
1058 if (*(args[1]) == 0) {
1059 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062 }
1063 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001064 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001065 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069}
1070
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 else if (!strcmp(args[0], "ulimit-n")) {
1072 if (global.rlimit_nofile != 0) {
1073 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001074 err_code |= ERR_ALERT;
1075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 }
1077 if (*(args[1]) == 0) {
1078 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 }
1082 global.rlimit_nofile = atol(args[1]);
1083 }
1084 else if (!strcmp(args[0], "chroot")) {
1085 if (global.chroot != NULL) {
1086 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001087 err_code |= ERR_ALERT;
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
1090 if (*(args[1]) == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 }
1095 global.chroot = strdup(args[1]);
1096 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097 else if (!strcmp(args[0], "description")) {
1098 int i, len=0;
1099 char *d;
1100
1101 if (!*args[1]) {
1102 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1103 file, linenum, args[0]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
1107
Willy Tarreau348acfe2014-04-14 15:00:39 +02001108 for (i = 1; *args[i]; i++)
1109 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001110
1111 if (global.desc)
1112 free(global.desc);
1113
1114 global.desc = d = (char *)calloc(1, len);
1115
Willy Tarreau348acfe2014-04-14 15:00:39 +02001116 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1117 for (i = 2; *args[i]; i++)
1118 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001119 }
1120 else if (!strcmp(args[0], "node")) {
1121 int i;
1122 char c;
1123
1124 for (i=0; args[1][i]; i++) {
1125 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001126 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1127 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001128 break;
1129 }
1130
1131 if (!i || args[1][i]) {
1132 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1133 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1134 file, linenum, args[0]);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
1137 }
1138
1139 if (global.node)
1140 free(global.node);
1141
1142 global.node = strdup(args[1]);
1143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 else if (!strcmp(args[0], "pidfile")) {
1145 if (global.pidfile != NULL) {
1146 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
1150 if (*(args[1]) == 0) {
1151 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
1155 global.pidfile = strdup(args[1]);
1156 }
Emeric Bruned760922010-10-22 17:59:25 +02001157 else if (!strcmp(args[0], "unix-bind")) {
1158 int cur_arg = 1;
1159 while (*(args[cur_arg])) {
1160 if (!strcmp(args[cur_arg], "prefix")) {
1161 if (global.unix_bind.prefix != NULL) {
1162 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1163 err_code |= ERR_ALERT;
1164 cur_arg += 2;
1165 continue;
1166 }
1167
1168 if (*(args[cur_arg+1]) == 0) {
1169 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
1172 }
1173 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1174 cur_arg += 2;
1175 continue;
1176 }
1177
1178 if (!strcmp(args[cur_arg], "mode")) {
1179
1180 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1181 cur_arg += 2;
1182 continue;
1183 }
1184
1185 if (!strcmp(args[cur_arg], "uid")) {
1186
1187 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1188 cur_arg += 2;
1189 continue;
1190 }
1191
1192 if (!strcmp(args[cur_arg], "gid")) {
1193
1194 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1195 cur_arg += 2;
1196 continue;
1197 }
1198
1199 if (!strcmp(args[cur_arg], "user")) {
1200 struct passwd *user;
1201
1202 user = getpwnam(args[cur_arg + 1]);
1203 if (!user) {
1204 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1205 file, linenum, args[0], args[cur_arg + 1 ]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
1208 }
1209
1210 global.unix_bind.ux.uid = user->pw_uid;
1211 cur_arg += 2;
1212 continue;
1213 }
1214
1215 if (!strcmp(args[cur_arg], "group")) {
1216 struct group *group;
1217
1218 group = getgrnam(args[cur_arg + 1]);
1219 if (!group) {
1220 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1221 file, linenum, args[0], args[cur_arg + 1 ]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225
1226 global.unix_bind.ux.gid = group->gr_gid;
1227 cur_arg += 2;
1228 continue;
1229 }
1230
Willy Tarreaub48f9582011-09-05 01:17:06 +02001231 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001232 file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 }
William Lallemand0f99e342011-10-12 17:50:54 +02001237 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1238 /* delete previous herited or defined syslog servers */
1239 struct logsrv *back;
1240 struct logsrv *tmp;
1241
1242 if (*(args[1]) != 0) {
1243 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1244 err_code |= ERR_ALERT | ERR_FATAL;
1245 goto out;
1246 }
1247
1248 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1249 LIST_DEL(&tmp->list);
1250 free(tmp);
1251 }
1252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001254 struct sockaddr_storage *sk;
1255 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001256 struct logsrv *logsrv;
1257
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 if (*(args[1]) == 0 || *(args[2]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 }
William Lallemand0f99e342011-10-12 17:50:54 +02001263
1264 logsrv = calloc(1, sizeof(struct logsrv));
1265
1266 logsrv->facility = get_log_facility(args[2]);
1267 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001269 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001270 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 }
1272
William Lallemand0f99e342011-10-12 17:50:54 +02001273 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001275 logsrv->level = get_log_level(args[3]);
1276 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001279 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 }
1281 }
1282
William Lallemand0f99e342011-10-12 17:50:54 +02001283 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001284 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001285 logsrv->minlvl = get_log_level(args[4]);
1286 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001287 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001288 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001289 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001290 }
1291 }
1292
Willy Tarreau902636f2013-03-10 19:44:48 +01001293 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001294 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001295 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001297 free(logsrv);
1298 goto out;
1299 }
1300 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001301
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001302 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001303 if (port1 != port2) {
1304 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1305 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001306 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001307 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001308 goto out;
1309 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001310
William Lallemand0f99e342011-10-12 17:50:54 +02001311 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001312 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001313 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315
William Lallemand0f99e342011-10-12 17:50:54 +02001316 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001317 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001318 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1319 char *name;
1320 int len;
1321
1322 if (global.log_send_hostname != NULL) {
1323 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1324 err_code |= ERR_ALERT;
1325 goto out;
1326 }
1327
1328 if (*(args[1]))
1329 name = args[1];
1330 else
1331 name = hostname;
1332
1333 len = strlen(name);
1334
1335 /* We'll add a space after the name to respect the log format */
1336 free(global.log_send_hostname);
1337 global.log_send_hostname = malloc(len + 2);
1338 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1339 }
Kevinm48936af2010-12-22 16:08:21 +00001340 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1341 if (*(args[1]) == 0) {
1342 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
1345 }
1346 free(global.log_tag);
1347 global.log_tag = strdup(args[1]);
1348 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001349 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1350 if (global.spread_checks != 0) {
1351 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001352 err_code |= ERR_ALERT;
1353 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001354 }
1355 if (*(args[1]) == 0) {
1356 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001357 err_code |= ERR_ALERT | ERR_FATAL;
1358 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001359 }
1360 global.spread_checks = atol(args[1]);
1361 if (global.spread_checks < 0 || global.spread_checks > 50) {
1362 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001366 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1367 const char *err;
1368 unsigned int val;
1369
1370
1371 if (*(args[1]) == 0) {
1372 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1373 err_code |= ERR_ALERT | ERR_FATAL;
1374 goto out;
1375 }
1376
1377 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1378 if (err) {
1379 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1380 err_code |= ERR_ALERT | ERR_FATAL;
1381 }
1382 global.max_spread_checks = val;
1383 if (global.max_spread_checks < 0) {
1384 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1385 err_code |= ERR_ALERT | ERR_FATAL;
1386 }
1387 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001388 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1389#ifdef USE_CPU_AFFINITY
1390 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001391 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001392 unsigned long cpus = 0;
1393
1394 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001395 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001396 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001397 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001398 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001399 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001400 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001401 proc = atol(args[1]);
1402 if (proc >= 1 && proc <= LONGBITS)
1403 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001404 }
1405
1406 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001407 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1408 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001409 err_code |= ERR_ALERT | ERR_FATAL;
1410 goto out;
1411 }
1412
1413 cur_arg = 2;
1414 while (*args[cur_arg]) {
1415 unsigned int low, high;
1416
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001417 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001418 char *dash = strchr(args[cur_arg], '-');
1419
1420 low = high = str2uic(args[cur_arg]);
1421 if (dash)
1422 high = str2uic(dash + 1);
1423
1424 if (high < low) {
1425 unsigned int swap = low;
1426 low = high;
1427 high = swap;
1428 }
1429
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001430 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001431 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001432 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
1435 }
1436
1437 while (low <= high)
1438 cpus |= 1UL << low++;
1439 }
1440 else {
1441 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1442 file, linenum, args[0], args[cur_arg]);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446 cur_arg++;
1447 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001448 for (i = 0; i < LONGBITS; i++)
1449 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001450 global.cpu_map[i] = cpus;
1451#else
1452 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto out;
1455#endif
1456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001458 struct cfg_kw_list *kwl;
1459 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001460 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001461
1462 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1463 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1464 if (kwl->kw[index].section != CFG_GLOBAL)
1465 continue;
1466 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001467 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001468 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001469 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001470 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001471 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001472 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001473 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001474 err_code |= ERR_WARN;
1475 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001476 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001477 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001478 }
1479 }
1480 }
1481
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001485
Willy Tarreau058e9072009-07-20 09:30:05 +02001486 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001487 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001488 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489}
1490
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001491void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001493 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 defproxy.mode = PR_MODE_TCP;
1495 defproxy.state = PR_STNEW;
1496 defproxy.maxconn = cfg_maxpconn;
1497 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001498
Simon Horman66183002013-02-23 10:16:43 +09001499 defproxy.defsrv.check.inter = DEF_CHKINTR;
1500 defproxy.defsrv.check.fastinter = 0;
1501 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001502 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1503 defproxy.defsrv.agent.fastinter = 0;
1504 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001505 defproxy.defsrv.check.rise = DEF_RISETIME;
1506 defproxy.defsrv.check.fall = DEF_FALLTIME;
1507 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1508 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001509 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001510 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001511 defproxy.defsrv.maxqueue = 0;
1512 defproxy.defsrv.minconn = 0;
1513 defproxy.defsrv.maxconn = 0;
1514 defproxy.defsrv.slowstart = 0;
1515 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1516 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1517 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518}
1519
Willy Tarreauade5ec42010-01-28 19:33:49 +01001520
Willy Tarreau63af98d2014-05-18 08:11:41 +02001521/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1522 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1523 * ERR_FATAL in case of error.
1524 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001525static int create_cond_regex_rule(const char *file, int line,
1526 struct proxy *px, int dir, int action, int flags,
1527 const char *cmd, const char *reg, const char *repl,
1528 const char **cond_start)
1529{
1530 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001531 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001532 const char *err;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001533 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001534 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001535
1536 if (px == &defproxy) {
1537 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001538 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001539 goto err;
1540 }
1541
1542 if (*reg == 0) {
1543 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001544 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001545 goto err;
1546 }
1547
1548 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001549 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001550
Willy Tarreau5321c422010-01-28 20:35:13 +01001551 if (cond_start &&
1552 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001553 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1554 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1555 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001556 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001557 goto err;
1558 }
1559 }
1560 else if (cond_start && **cond_start) {
1561 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1562 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001563 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001564 goto err;
1565 }
1566
Willy Tarreau63af98d2014-05-18 08:11:41 +02001567 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001568 (dir == SMP_OPT_DIR_REQ) ?
1569 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1570 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1571 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001572
Willy Tarreauade5ec42010-01-28 19:33:49 +01001573 preg = calloc(1, sizeof(regex_t));
1574 if (!preg) {
1575 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001576 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001577 goto err;
1578 }
1579
1580 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1581 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001582 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001583 goto err;
1584 }
1585
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001586 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001587 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001588 if (repl && err) {
1589 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1590 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001591 ret_code |= ERR_ALERT | ERR_FATAL;
1592 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001593 }
1594
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001595 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001596 ret_code |= ERR_WARN;
1597
1598 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001599
Willy Tarreau63af98d2014-05-18 08:11:41 +02001600 err_free:
1601 regfree(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001602 err:
1603 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001604 free(errmsg);
1605 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001606}
1607
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001609 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001610 * Returns the error code, 0 if OK, or any combination of :
1611 * - ERR_ABORT: must abort ASAP
1612 * - ERR_FATAL: we can continue parsing but not start the service
1613 * - ERR_WARN: a warning has been emitted
1614 * - ERR_ALERT: an alert has been emitted
1615 * Only the two first ones can stop processing, the two others are just
1616 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001618int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1619{
1620 static struct peers *curpeers = NULL;
1621 struct peer *newpeer = NULL;
1622 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001623 struct bind_conf *bind_conf;
1624 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001625 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001626 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001627
1628 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001629 if (!*args[1]) {
1630 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001631 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001632 goto out;
1633 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001634
1635 err = invalid_char(args[1]);
1636 if (err) {
1637 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1638 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001639 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001640 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001641 }
1642
1643 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1644 /*
1645 * If there are two proxies with the same name only following
1646 * combinations are allowed:
1647 */
1648 if (strcmp(curpeers->id, args[1]) == 0) {
1649 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1650 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1651 err_code |= ERR_WARN;
1652 }
1653 }
1654
1655 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1656 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1657 err_code |= ERR_ALERT | ERR_ABORT;
1658 goto out;
1659 }
1660
1661 curpeers->next = peers;
1662 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001663 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001664 curpeers->conf.line = linenum;
1665 curpeers->last_change = now.tv_sec;
1666 curpeers->id = strdup(args[1]);
1667 }
1668 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001669 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001670 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001671 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001672
1673 if (!*args[2]) {
1674 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1675 file, linenum, args[0]);
1676 err_code |= ERR_ALERT | ERR_FATAL;
1677 goto out;
1678 }
1679
1680 err = invalid_char(args[1]);
1681 if (err) {
1682 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1683 file, linenum, *err, args[1]);
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687
1688 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1689 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1690 err_code |= ERR_ALERT | ERR_ABORT;
1691 goto out;
1692 }
1693
1694 /* the peers are linked backwards first */
1695 curpeers->count++;
1696 newpeer->next = curpeers->remote;
1697 curpeers->remote = newpeer;
1698 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001699 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001700 newpeer->conf.line = linenum;
1701
1702 newpeer->last_change = now.tv_sec;
1703 newpeer->id = strdup(args[1]);
1704
Willy Tarreau902636f2013-03-10 19:44:48 +01001705 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001706 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001707 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001710 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001711
1712 proto = protocol_by_family(sk->ss_family);
1713 if (!proto || !proto->connect) {
1714 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1715 file, linenum, args[0], args[1]);
1716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
1718 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001719
1720 if (port1 != port2) {
1721 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1722 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726
Willy Tarreau2aa38802013-02-20 19:20:59 +01001727 if (!port1) {
1728 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1729 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
1732 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001733
Emeric Brun32da3c42010-09-23 18:39:19 +02001734 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001735 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001736 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001737 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001738
Emeric Brun32da3c42010-09-23 18:39:19 +02001739 if (strcmp(newpeer->id, localpeer) == 0) {
1740 /* Current is local peer, it define a frontend */
1741 newpeer->local = 1;
1742
1743 if (!curpeers->peers_fe) {
1744 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1745 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1746 err_code |= ERR_ALERT | ERR_ABORT;
1747 goto out;
1748 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001749
Willy Tarreau237250c2011-07-29 01:49:03 +02001750 init_new_proxy(curpeers->peers_fe);
1751 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001752
1753 curpeers->peers_fe->last_change = now.tv_sec;
1754 curpeers->peers_fe->id = strdup(args[1]);
1755 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001756 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001757 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1758 curpeers->peers_fe->timeout.connect = 5000;
1759 curpeers->peers_fe->accept = peer_accept;
1760 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001761 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1762 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001763
1764 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1765
Willy Tarreau902636f2013-03-10 19:44:48 +01001766 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1767 if (errmsg && *errmsg) {
1768 indent_msg(&errmsg, 2);
1769 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001770 }
1771 else
1772 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1773 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001774 err_code |= ERR_FATAL;
1775 goto out;
1776 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001777
1778 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001779 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001780 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1781 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1782 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1783 l->accept = session_accept;
1784 l->handler = process_session;
1785 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1786 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1787 global.maxsock += l->maxconn;
1788 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001789 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001790 else {
1791 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1792 file, linenum, args[0], args[1],
1793 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1794 err_code |= ERR_FATAL;
1795 goto out;
1796 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001797 }
1798 } /* neither "peer" nor "peers" */
1799 else if (*args[0] != 0) {
1800 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804
1805out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001806 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001807 return err_code;
1808}
1809
Willy Tarreau3842f002009-06-14 11:39:52 +02001810int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811{
1812 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001813 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001814 int rc;
1815 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001816 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001817 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001818 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001819 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001820 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 if (!strcmp(args[0], "listen"))
1823 rc = PR_CAP_LISTEN;
1824 else if (!strcmp(args[0], "frontend"))
1825 rc = PR_CAP_FE | PR_CAP_RS;
1826 else if (!strcmp(args[0], "backend"))
1827 rc = PR_CAP_BE | PR_CAP_RS;
1828 else if (!strcmp(args[0], "ruleset"))
1829 rc = PR_CAP_RS;
1830 else
1831 rc = PR_CAP_NONE;
1832
1833 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001834 struct ebpt_node *node;
1835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 if (!*args[1]) {
1837 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1838 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1839 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001840 err_code |= ERR_ALERT | ERR_ABORT;
1841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001843
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001844 err = invalid_char(args[1]);
1845 if (err) {
1846 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1847 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001849 }
1850
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001851 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1852 curproxy = container_of(node, struct proxy, conf.by_name);
1853
1854 if (strcmp(curproxy->id, args[1]) != 0)
1855 break;
1856
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001857 /*
1858 * If there are two proxies with the same name only following
1859 * combinations are allowed:
1860 *
1861 * listen backend frontend ruleset
1862 * listen - - - -
1863 * backend - - OK -
1864 * frontend - OK - -
1865 * ruleset - - - -
1866 */
1867
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001868 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1869 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001870 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1871 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1872 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001873 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001874 }
1875 }
1876
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1878 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001879 err_code |= ERR_ALERT | ERR_ABORT;
1880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001882
Willy Tarreau97cb7802010-01-03 20:23:58 +01001883 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 curproxy->next = proxy;
1885 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001886 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1887 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001888 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001891 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892
1893 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001894 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001895 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001896
Willy Tarreau4348fad2012-09-20 16:48:07 +02001897 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1898
Willy Tarreau902636f2013-03-10 19:44:48 +01001899 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1900 if (errmsg && *errmsg) {
1901 indent_msg(&errmsg, 2);
1902 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001903 }
1904 else
1905 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1906 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001907 err_code |= ERR_FATAL;
1908 goto out;
1909 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001910
Willy Tarreau4348fad2012-09-20 16:48:07 +02001911 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001912 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 }
1915
1916 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001917 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001918 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001919
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001922 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001923 curproxy->no_options = defproxy.no_options;
1924 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001925 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001926 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001927 curproxy->except_net = defproxy.except_net;
1928 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001929 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001930 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001932 if (defproxy.fwdfor_hdr_len) {
1933 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1934 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1935 }
1936
Willy Tarreaub86db342009-11-30 11:50:16 +01001937 if (defproxy.orgto_hdr_len) {
1938 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1939 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1940 }
1941
Mark Lamourinec2247f02012-01-04 13:02:01 -05001942 if (defproxy.server_id_hdr_len) {
1943 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1944 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1945 }
1946
Willy Tarreau977b8e42006-12-29 14:19:17 +01001947 if (curproxy->cap & PR_CAP_FE) {
1948 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001949 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001950 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951
1952 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001953 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1954 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955
1956 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959 if (curproxy->cap & PR_CAP_BE) {
1960 curproxy->fullconn = defproxy.fullconn;
1961 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001962 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001964 if (defproxy.check_req) {
1965 curproxy->check_req = calloc(1, defproxy.check_len);
1966 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1967 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001968 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001970 if (defproxy.expect_str) {
1971 curproxy->expect_str = strdup(defproxy.expect_str);
1972 if (defproxy.expect_regex) {
1973 /* note: this regex is known to be valid */
1974 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1975 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1976 }
1977 }
1978
Willy Tarreau67402132012-05-31 20:40:20 +02001979 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001980 if (defproxy.cookie_name)
1981 curproxy->cookie_name = strdup(defproxy.cookie_name);
1982 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001983 if (defproxy.cookie_domain)
1984 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001985
Willy Tarreau31936852010-10-06 16:59:56 +02001986 if (defproxy.cookie_maxidle)
1987 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1988
1989 if (defproxy.cookie_maxlife)
1990 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1991
Emeric Brun647caf12009-06-30 17:57:00 +02001992 if (defproxy.rdp_cookie_name)
1993 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1994 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1995
Willy Tarreau01732802007-11-01 22:48:15 +01001996 if (defproxy.url_param_name)
1997 curproxy->url_param_name = strdup(defproxy.url_param_name);
1998 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001999
Benoitaffb4812009-03-25 13:02:10 +01002000 if (defproxy.hh_name)
2001 curproxy->hh_name = strdup(defproxy.hh_name);
2002 curproxy->hh_len = defproxy.hh_len;
2003 curproxy->hh_match_domain = defproxy.hh_match_domain;
2004
Willy Tarreauef9a3602012-12-08 22:29:20 +01002005 if (defproxy.conn_src.iface_name)
2006 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2007 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002008 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002009#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002010 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002011#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002014 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002015 if (defproxy.capture_name)
2016 curproxy->capture_name = strdup(defproxy.capture_name);
2017 curproxy->capture_namelen = defproxy.capture_namelen;
2018 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020
Willy Tarreau977b8e42006-12-29 14:19:17 +01002021 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002022 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002023 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002024 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002025 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002026 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002027 curproxy->mon_net = defproxy.mon_net;
2028 curproxy->mon_mask = defproxy.mon_mask;
2029 if (defproxy.monitor_uri)
2030 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2031 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002032 if (defproxy.defbe.name)
2033 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002034
2035 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002036 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2037 if (curproxy->conf.logformat_string &&
2038 curproxy->conf.logformat_string != default_http_log_format &&
2039 curproxy->conf.logformat_string != default_tcp_log_format &&
2040 curproxy->conf.logformat_string != clf_http_log_format)
2041 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2042
2043 if (defproxy.conf.lfs_file) {
2044 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2045 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 }
2048
2049 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002050 curproxy->timeout.connect = defproxy.timeout.connect;
2051 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002052 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002053 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002054 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002055 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002056 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002057 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002058 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002059 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002060 }
2061
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002063 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002064
2065 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002066 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002067 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002068 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002069 LIST_INIT(&node->list);
2070 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2071 }
2072
Willy Tarreau62a61232013-04-12 18:13:46 +02002073 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2074 if (curproxy->conf.uniqueid_format_string)
2075 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2076
2077 if (defproxy.conf.uif_file) {
2078 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2079 curproxy->conf.uif_line = defproxy.conf.uif_line;
2080 }
William Lallemanda73203e2012-03-12 12:48:57 +01002081
2082 /* copy default header unique id */
2083 if (defproxy.header_unique_id)
2084 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2085
William Lallemand82fe75c2012-10-23 10:25:10 +02002086 /* default compression options */
2087 if (defproxy.comp != NULL) {
2088 curproxy->comp = calloc(1, sizeof(struct comp));
2089 curproxy->comp->algos = defproxy.comp->algos;
2090 curproxy->comp->types = defproxy.comp->types;
2091 }
2092
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002094 curproxy->conf.used_listener_id = EB_ROOT;
2095 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002096
Willy Tarreau93893792009-07-23 13:19:11 +02002097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 }
2099 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2100 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002101 /* FIXME-20070101: we should do this too at the end of the
2102 * config parsing to free all default values.
2103 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002104 free(defproxy.check_req);
2105 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002106 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002107 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002108 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002109 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002110 free(defproxy.capture_name);
2111 free(defproxy.monitor_uri);
2112 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002113 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002114 free(defproxy.fwdfor_hdr_name);
2115 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002116 free(defproxy.orgto_hdr_name);
2117 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002118 free(defproxy.server_id_hdr_name);
2119 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002120 free(defproxy.expect_str);
2121 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002122
Willy Tarreau62a61232013-04-12 18:13:46 +02002123 if (defproxy.conf.logformat_string != default_http_log_format &&
2124 defproxy.conf.logformat_string != default_tcp_log_format &&
2125 defproxy.conf.logformat_string != clf_http_log_format)
2126 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002127
Willy Tarreau62a61232013-04-12 18:13:46 +02002128 free(defproxy.conf.uniqueid_format_string);
2129 free(defproxy.conf.lfs_file);
2130 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002131
Willy Tarreaua534fea2008-08-03 12:19:50 +02002132 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002133 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002134
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 /* we cannot free uri_auth because it might already be used */
2136 init_default_instance();
2137 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002138 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2139 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002140 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 }
2143 else if (curproxy == NULL) {
2144 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002148
2149 /* update the current file and line being parsed */
2150 curproxy->conf.args.file = curproxy->conf.file;
2151 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152
2153 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002154 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2155 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2156 if (err_code & ERR_FATAL)
2157 goto out;
2158 }
2159 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002160 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002161 int cur_arg;
2162
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 if (curproxy == &defproxy) {
2164 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002168 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002169 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170
Willy Tarreau24709282013-03-10 21:32:12 +01002171 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002172 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002177
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002178 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002179
2180 /* use default settings for unix sockets */
2181 bind_conf->ux.uid = global.unix_bind.ux.uid;
2182 bind_conf->ux.gid = global.unix_bind.ux.gid;
2183 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002184
2185 /* NOTE: the following line might create several listeners if there
2186 * are comma-separated IPs or port ranges. So all further processing
2187 * will have to be applied to all listeners created after last_listen.
2188 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002189 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2190 if (errmsg && *errmsg) {
2191 indent_msg(&errmsg, 2);
2192 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002193 }
2194 else
2195 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2196 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002200
Willy Tarreau4348fad2012-09-20 16:48:07 +02002201 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2202 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002203 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002204 }
2205
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002206 cur_arg = 2;
2207 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002208 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002209 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002210 char *err;
2211
Willy Tarreau26982662012-09-12 23:17:10 +02002212 kw = bind_find_kw(args[cur_arg]);
2213 if (kw) {
2214 char *err = NULL;
2215 int code;
2216
2217 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002218 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2219 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002220 cur_arg += 1 + kw->skip ;
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224
Willy Tarreau4348fad2012-09-20 16:48:07 +02002225 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002226 err_code |= code;
2227
2228 if (code) {
2229 if (err && *err) {
2230 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002231 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002232 }
2233 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002234 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2235 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002236 if (code & ERR_FATAL) {
2237 free(err);
2238 cur_arg += 1 + kw->skip;
2239 goto out;
2240 }
2241 }
2242 free(err);
2243 cur_arg += 1 + kw->skip;
2244 continue;
2245 }
2246
Willy Tarreau8638f482012-09-18 18:01:17 +02002247 err = NULL;
2248 if (!bind_dumped) {
2249 bind_dump_kws(&err);
2250 indent_msg(&err, 4);
2251 bind_dumped = 1;
2252 }
2253
2254 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2255 file, linenum, args[0], args[1], args[cur_arg],
2256 err ? " Registered keywords :" : "", err ? err : "");
2257 free(err);
2258
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002261 }
Willy Tarreau93893792009-07-23 13:19:11 +02002262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 }
2264 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002265 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2267 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002271 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 /* flush useless bits */
2275 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002278 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002281
Willy Tarreau1c47f852006-07-09 08:22:27 +02002282 if (!*args[1]) {
2283 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2284 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002287 }
2288
Willy Tarreaua534fea2008-08-03 12:19:50 +02002289 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002290 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002291 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002292 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002293 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2294
Willy Tarreau93893792009-07-23 13:19:11 +02002295 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2298 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2299 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2300 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2301 else {
2302 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
2306 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002307 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002308 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002309
2310 if (curproxy == &defproxy) {
2311 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2312 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002315 }
2316
2317 if (!*args[1]) {
2318 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2319 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002322 }
2323
2324 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002325 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002326
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002327 if (curproxy->uuid <= 0) {
2328 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002329 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002332 }
2333
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002334 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2335 if (node) {
2336 struct proxy *target = container_of(node, struct proxy, conf.id);
2337 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2338 file, linenum, proxy_type_str(curproxy), curproxy->id,
2339 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
2343 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002344 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002345 else if (!strcmp(args[0], "description")) {
2346 int i, len=0;
2347 char *d;
2348
Cyril Bonté99ed3272010-01-24 23:29:44 +01002349 if (curproxy == &defproxy) {
2350 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2351 file, linenum, args[0]);
2352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
2354 }
2355
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002356 if (!*args[1]) {
2357 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2358 file, linenum, args[0]);
2359 return -1;
2360 }
2361
Willy Tarreau348acfe2014-04-14 15:00:39 +02002362 for (i = 1; *args[i]; i++)
2363 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002364
2365 d = (char *)calloc(1, len);
2366 curproxy->desc = d;
2367
Willy Tarreau348acfe2014-04-14 15:00:39 +02002368 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2369 for (i = 2; *args[i]; i++)
2370 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002371
2372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2374 curproxy->state = PR_STSTOPPED;
2375 }
2376 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2377 curproxy->state = PR_STNEW;
2378 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002379 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2380 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002381 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002382
2383 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002384 unsigned int low, high;
2385
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002386 if (strcmp(args[cur_arg], "all") == 0) {
2387 set = 0;
2388 break;
2389 }
2390 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002391 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002392 }
2393 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002394 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002395 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002396 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002397 char *dash = strchr(args[cur_arg], '-');
2398
2399 low = high = str2uic(args[cur_arg]);
2400 if (dash)
2401 high = str2uic(dash + 1);
2402
2403 if (high < low) {
2404 unsigned int swap = low;
2405 low = high;
2406 high = swap;
2407 }
2408
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002409 if (low < 1 || high > LONGBITS) {
2410 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2411 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002414 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002415 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002416 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002417 }
2418 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002419 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2420 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002423 }
2424 cur_arg++;
2425 }
2426 curproxy->bind_proc = set;
2427 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002428 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002429 if (curproxy == &defproxy) {
2430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002433 }
2434
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002435 err = invalid_char(args[1]);
2436 if (err) {
2437 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2438 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002440 }
2441
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002442 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002443 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2444 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002447 }
2448 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2450 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451
Willy Tarreau977b8e42006-12-29 14:19:17 +01002452 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002454
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 if (*(args[1]) == 0) {
2456 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2457 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002461
Willy Tarreau67402132012-05-31 20:40:20 +02002462 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002463 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002464 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002465 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 curproxy->cookie_name = strdup(args[1]);
2467 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002468
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 cur_arg = 2;
2470 while (*(args[cur_arg])) {
2471 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002472 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 }
2474 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002475 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 }
2477 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002478 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 }
2480 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002481 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 }
2483 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002484 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002486 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002487 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002490 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002492 else if (!strcmp(args[cur_arg], "httponly")) {
2493 curproxy->ck_opts |= PR_CK_HTTPONLY;
2494 }
2495 else if (!strcmp(args[cur_arg], "secure")) {
2496 curproxy->ck_opts |= PR_CK_SECURE;
2497 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002498 else if (!strcmp(args[cur_arg], "domain")) {
2499 if (!*args[cur_arg + 1]) {
2500 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2501 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002504 }
2505
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002506 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002507 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002508 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2509 " dots nor does not start with a dot."
2510 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002511 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002512 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002513 }
2514
2515 err = invalid_domainchar(args[cur_arg + 1]);
2516 if (err) {
2517 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2518 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002521 }
2522
Willy Tarreau68a897b2009-12-03 23:28:34 +01002523 if (!curproxy->cookie_domain) {
2524 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2525 } else {
2526 /* one domain was already specified, add another one by
2527 * building the string which will be returned along with
2528 * the cookie.
2529 */
2530 char *new_ptr;
2531 int new_len = strlen(curproxy->cookie_domain) +
2532 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2533 new_ptr = malloc(new_len);
2534 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2535 free(curproxy->cookie_domain);
2536 curproxy->cookie_domain = new_ptr;
2537 }
Willy Tarreau31936852010-10-06 16:59:56 +02002538 cur_arg++;
2539 }
2540 else if (!strcmp(args[cur_arg], "maxidle")) {
2541 unsigned int maxidle;
2542 const char *res;
2543
2544 if (!*args[cur_arg + 1]) {
2545 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2546 file, linenum, args[cur_arg]);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
2549 }
2550
2551 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2552 if (res) {
2553 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2554 file, linenum, *res, args[cur_arg]);
2555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
2557 }
2558 curproxy->cookie_maxidle = maxidle;
2559 cur_arg++;
2560 }
2561 else if (!strcmp(args[cur_arg], "maxlife")) {
2562 unsigned int maxlife;
2563 const char *res;
2564
2565 if (!*args[cur_arg + 1]) {
2566 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2567 file, linenum, args[cur_arg]);
2568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
2570 }
2571
2572 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2573 if (res) {
2574 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2575 file, linenum, *res, args[cur_arg]);
2576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
2578 }
2579 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002580 cur_arg++;
2581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002583 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 +02002584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
2588 cur_arg++;
2589 }
Willy Tarreau67402132012-05-31 20:40:20 +02002590 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 }
2595
Willy Tarreau67402132012-05-31 20:40:20 +02002596 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2598 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002601
Willy Tarreau67402132012-05-31 20:40:20 +02002602 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002603 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2604 file, linenum);
2605 err_code |= ERR_ALERT | ERR_FATAL;
2606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002608 else if (!strcmp(args[0], "persist")) { /* persist */
2609 if (*(args[1]) == 0) {
2610 Alert("parsing [%s:%d] : missing persist method.\n",
2611 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002614 }
2615
2616 if (!strncmp(args[1], "rdp-cookie", 10)) {
2617 curproxy->options2 |= PR_O2_RDPC_PRST;
2618
Emeric Brunb982a3d2010-01-04 15:45:53 +01002619 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002620 const char *beg, *end;
2621
2622 beg = args[1] + 11;
2623 end = strchr(beg, ')');
2624
2625 if (!end || end == beg) {
2626 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2627 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002630 }
2631
2632 free(curproxy->rdp_cookie_name);
2633 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2634 curproxy->rdp_cookie_len = end-beg;
2635 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002636 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002637 free(curproxy->rdp_cookie_name);
2638 curproxy->rdp_cookie_name = strdup("msts");
2639 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2640 }
2641 else { /* syntax */
2642 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2643 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002646 }
2647 }
2648 else {
2649 Alert("parsing [%s:%d] : unknown persist method.\n",
2650 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002653 }
2654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002656 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002658 if (curproxy == &defproxy) {
2659 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663
Willy Tarreau977b8e42006-12-29 14:19:17 +01002664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002665 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002666
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002668 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 }
2673 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002674 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 curproxy->appsession_name = strdup(args[1]);
2676 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2677 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002678 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2679 if (err) {
2680 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2681 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002684 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002685 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002686
Willy Tarreau51041c72007-09-09 21:56:53 +02002687 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2688 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_ABORT;
2690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002692
2693 cur_arg = 6;
2694 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002695 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2696 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002697 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002698 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002699 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002700 } else if (!strcmp(args[cur_arg], "prefix")) {
2701 curproxy->options2 |= PR_O2_AS_PFX;
2702 } else if (!strcmp(args[cur_arg], "mode")) {
2703 if (!*args[cur_arg + 1]) {
2704 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2705 file, linenum, args[0], args[cur_arg]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
2709
2710 cur_arg++;
2711 if (!strcmp(args[cur_arg], "query-string")) {
2712 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2713 curproxy->options2 |= PR_O2_AS_M_QS;
2714 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2715 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2716 curproxy->options2 |= PR_O2_AS_M_PP;
2717 } else {
2718 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002723 cur_arg++;
2724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 } /* Url App Session */
2726 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002727 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002731 if (curproxy == &defproxy) {
2732 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 if (*(args[4]) == 0) {
2738 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2739 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002743 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002744 curproxy->capture_name = strdup(args[2]);
2745 curproxy->capture_namelen = strlen(curproxy->capture_name);
2746 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 curproxy->to_log |= LW_COOKIE;
2748 }
2749 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2750 struct cap_hdr *hdr;
2751
2752 if (curproxy == &defproxy) {
2753 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 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
2757
2758 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2759 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2760 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764
2765 hdr = calloc(sizeof(struct cap_hdr), 1);
2766 hdr->next = curproxy->req_cap;
2767 hdr->name = strdup(args[3]);
2768 hdr->namelen = strlen(args[3]);
2769 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002770 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 hdr->index = curproxy->nb_req_cap++;
2772 curproxy->req_cap = hdr;
2773 curproxy->to_log |= LW_REQHDR;
2774 }
2775 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2776 struct cap_hdr *hdr;
2777
2778 if (curproxy == &defproxy) {
2779 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 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
2783
2784 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2785 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2786 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_ALERT | ERR_FATAL;
2788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 }
2790 hdr = calloc(sizeof(struct cap_hdr), 1);
2791 hdr->next = curproxy->rsp_cap;
2792 hdr->name = strdup(args[3]);
2793 hdr->namelen = strlen(args[3]);
2794 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002795 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 hdr->index = curproxy->nb_rsp_cap++;
2797 curproxy->rsp_cap = hdr;
2798 curproxy->to_log |= LW_RSPHDR;
2799 }
2800 else {
2801 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2802 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 }
2806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002810
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 if (*(args[1]) == 0) {
2812 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2813 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002816 }
2817 curproxy->conn_retries = atol(args[1]);
2818 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002819 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002820 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002821
2822 if (curproxy == &defproxy) {
2823 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
2826 }
2827
Willy Tarreau20b0de52012-12-24 15:45:22 +01002828 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2829 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2830 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2831 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002832 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002833 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2834 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 +01002835 file, linenum, args[0]);
2836 err_code |= ERR_WARN;
2837 }
2838
Willy Tarreauff011f22011-01-06 17:51:27 +01002839 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002840
Willy Tarreauff011f22011-01-06 17:51:27 +01002841 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002842 err_code |= ERR_ALERT | ERR_ABORT;
2843 goto out;
2844 }
2845
Willy Tarreau5002f572014-04-23 01:32:02 +02002846 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002847 err_code |= warnif_cond_conflicts(rule->cond,
2848 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2849 file, linenum);
2850
Willy Tarreauff011f22011-01-06 17:51:27 +01002851 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002852 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002853 else if (!strcmp(args[0], "http-response")) { /* response access control */
2854 struct http_res_rule *rule;
2855
2856 if (curproxy == &defproxy) {
2857 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861
2862 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2863 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2864 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2865 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2866 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2867 file, linenum, args[0]);
2868 err_code |= ERR_WARN;
2869 }
2870
2871 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2872
2873 if (!rule) {
2874 err_code |= ERR_ALERT | ERR_ABORT;
2875 goto out;
2876 }
2877
2878 err_code |= warnif_cond_conflicts(rule->cond,
2879 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2880 file, linenum);
2881
2882 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2883 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002884 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2885 /* set the header name and length into the proxy structure */
2886 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2887 err_code |= ERR_WARN;
2888
2889 if (!*args[1]) {
2890 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2891 file, linenum, args[0]);
2892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
2895
2896 /* set the desired header name */
2897 free(curproxy->server_id_hdr_name);
2898 curproxy->server_id_hdr_name = strdup(args[1]);
2899 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2900 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002901 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002902 struct http_req_rule *rule;
2903
Willy Tarreaub099aca2008-10-12 17:26:37 +02002904 if (curproxy == &defproxy) {
2905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002908 }
2909
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002910 /* emulate "block" using "http-request block". Since these rules are supposed to
2911 * be processed before all http-request rules, we put them into their own list
2912 * and will insert them at the end.
2913 */
2914 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2915 if (!rule) {
2916 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002917 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002918 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002919 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2920 err_code |= warnif_cond_conflicts(rule->cond,
2921 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2922 file, linenum);
2923 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002924
2925 if (!already_warned(WARN_BLOCK_DEPRECATED))
2926 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of 'http-request deny' which uses the exact same syntax. The rules are translated but support might disappear in a future version.\n", file, linenum, args[0]);
2927
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002928 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002929 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002930 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002931
Cyril Bonté99ed3272010-01-24 23:29:44 +01002932 if (curproxy == &defproxy) {
2933 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
2936 }
2937
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002938 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002939 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2940 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002943 }
2944
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002945 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002946 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002947 err_code |= warnif_cond_conflicts(rule->cond,
2948 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2949 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002950 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002951 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002952 struct switching_rule *rule;
2953
Willy Tarreaub099aca2008-10-12 17:26:37 +02002954 if (curproxy == &defproxy) {
2955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002958 }
2959
Willy Tarreau55ea7572007-06-17 19:56:27 +02002960 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002961 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002962
2963 if (*(args[1]) == 0) {
2964 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002967 }
2968
Willy Tarreauf51658d2014-04-23 01:21:56 +02002969 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2970 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2971 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2972 file, linenum, errmsg);
2973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
2975 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002976
Willy Tarreauf51658d2014-04-23 01:21:56 +02002977 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002978 }
2979
2980 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2981 rule->cond = cond;
2982 rule->be.name = strdup(args[1]);
2983 LIST_INIT(&rule->list);
2984 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2985 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002986 else if (strcmp(args[0], "use-server") == 0) {
2987 struct server_rule *rule;
2988
2989 if (curproxy == &defproxy) {
2990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
2995 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2996 err_code |= ERR_WARN;
2997
2998 if (*(args[1]) == 0) {
2999 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
3002 }
3003
3004 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3005 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3006 file, linenum, args[0]);
3007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
3009 }
3010
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003011 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3012 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3013 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003018 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003019
3020 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3021 rule->cond = cond;
3022 rule->srv.name = strdup(args[1]);
3023 LIST_INIT(&rule->list);
3024 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3025 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3026 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003027 else if ((!strcmp(args[0], "force-persist")) ||
3028 (!strcmp(args[0], "ignore-persist"))) {
3029 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003030
3031 if (curproxy == &defproxy) {
3032 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
3036
3037 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3038 err_code |= ERR_WARN;
3039
Willy Tarreauef6494c2010-01-28 17:12:36 +01003040 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003041 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3042 file, linenum, args[0]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003047 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3048 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3049 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003054 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3055 * where force-persist is applied.
3056 */
3057 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003058
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003059 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003060 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003061 if (!strcmp(args[0], "force-persist")) {
3062 rule->type = PERSIST_TYPE_FORCE;
3063 } else {
3064 rule->type = PERSIST_TYPE_IGNORE;
3065 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003066 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003067 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003068 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003069 else if (!strcmp(args[0], "stick-table")) {
3070 int myidx = 1;
3071
Emeric Brun32da3c42010-09-23 18:39:19 +02003072 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003073 curproxy->table.type = (unsigned int)-1;
3074 while (*args[myidx]) {
3075 const char *err;
3076
3077 if (strcmp(args[myidx], "size") == 0) {
3078 myidx++;
3079 if (!*(args[myidx])) {
3080 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3081 file, linenum, args[myidx-1]);
3082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
3085 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3086 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3087 file, linenum, *err, args[myidx-1]);
3088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
3090 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003091 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003092 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003093 else if (strcmp(args[myidx], "peers") == 0) {
3094 myidx++;
Godbach50523162013-12-11 19:48:57 +08003095 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003096 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3097 file, linenum, args[myidx-1]);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
Godbach50523162013-12-11 19:48:57 +08003100 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003101 curproxy->table.peers.name = strdup(args[myidx++]);
3102 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003103 else if (strcmp(args[myidx], "expire") == 0) {
3104 myidx++;
3105 if (!*(args[myidx])) {
3106 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3107 file, linenum, args[myidx-1]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3112 if (err) {
3113 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3114 file, linenum, *err, args[myidx-1]);
3115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
3117 }
3118 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003119 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003120 }
3121 else if (strcmp(args[myidx], "nopurge") == 0) {
3122 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003123 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003124 }
3125 else if (strcmp(args[myidx], "type") == 0) {
3126 myidx++;
3127 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3128 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3129 file, linenum, args[myidx]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003133 /* myidx already points to next arg */
3134 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003135 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003136 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003137 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003138
3139 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003140 nw = args[myidx];
3141 while (*nw) {
3142 /* the "store" keyword supports a comma-separated list */
3143 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003144 sa = NULL; /* store arg */
3145 while (*nw && *nw != ',') {
3146 if (*nw == '(') {
3147 *nw = 0;
3148 sa = ++nw;
3149 while (*nw != ')') {
3150 if (!*nw) {
3151 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3152 file, linenum, args[0], cw);
3153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
3155 }
3156 nw++;
3157 }
3158 *nw = '\0';
3159 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003160 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003161 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003162 if (*nw)
3163 *nw++ = '\0';
3164 type = stktable_get_data_type(cw);
3165 if (type < 0) {
3166 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3167 file, linenum, args[0], cw);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
Willy Tarreauac782882010-06-20 10:41:54 +02003171
3172 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3173 switch (err) {
3174 case PE_NONE: break;
3175 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003176 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3177 file, linenum, args[0], cw);
3178 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003179 break;
3180
3181 case PE_ARG_MISSING:
3182 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3183 file, linenum, args[0], cw);
3184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
3186
3187 case PE_ARG_NOT_USED:
3188 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3189 file, linenum, args[0], cw);
3190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
3192
3193 default:
3194 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3195 file, linenum, args[0], cw);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003198 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003199 }
3200 myidx++;
3201 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003202 else {
3203 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3204 file, linenum, args[myidx]);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003207 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003208 }
3209
3210 if (!curproxy->table.size) {
3211 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3212 file, linenum);
3213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
3215 }
3216
3217 if (curproxy->table.type == (unsigned int)-1) {
3218 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3219 file, linenum);
3220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
3222 }
3223 }
3224 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003225 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003226 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003227 int myidx = 0;
3228 const char *name = NULL;
3229 int flags;
3230
3231 if (curproxy == &defproxy) {
3232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
3235 }
3236
3237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3238 err_code |= ERR_WARN;
3239 goto out;
3240 }
3241
3242 myidx++;
3243 if ((strcmp(args[myidx], "store") == 0) ||
3244 (strcmp(args[myidx], "store-request") == 0)) {
3245 myidx++;
3246 flags = STK_IS_STORE;
3247 }
3248 else if (strcmp(args[myidx], "store-response") == 0) {
3249 myidx++;
3250 flags = STK_IS_STORE | STK_ON_RSP;
3251 }
3252 else if (strcmp(args[myidx], "match") == 0) {
3253 myidx++;
3254 flags = STK_IS_MATCH;
3255 }
3256 else if (strcmp(args[myidx], "on") == 0) {
3257 myidx++;
3258 flags = STK_IS_MATCH | STK_IS_STORE;
3259 }
3260 else {
3261 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265
3266 if (*(args[myidx]) == 0) {
3267 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003272 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003273 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003274 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003275 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278 }
3279
3280 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003281 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3282 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3283 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003284 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003285 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003286 goto out;
3287 }
3288 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003289 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3290 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3291 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003292 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003293 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003294 goto out;
3295 }
3296 }
3297
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003298 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003299 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003300
Emeric Brunb982a3d2010-01-04 15:45:53 +01003301 if (strcmp(args[myidx], "table") == 0) {
3302 myidx++;
3303 name = args[myidx++];
3304 }
3305
Willy Tarreauef6494c2010-01-28 17:12:36 +01003306 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003307 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3308 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3309 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003310 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003311 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003312 goto out;
3313 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003314 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003315 else if (*(args[myidx])) {
3316 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3317 file, linenum, args[0], args[myidx]);
3318 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003319 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003320 goto out;
3321 }
Emeric Brun97679e72010-09-23 17:56:44 +02003322 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003323 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003324 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003325 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003326
Emeric Brunb982a3d2010-01-04 15:45:53 +01003327 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3328 rule->cond = cond;
3329 rule->expr = expr;
3330 rule->flags = flags;
3331 rule->table.name = name ? strdup(name) : NULL;
3332 LIST_INIT(&rule->list);
3333 if (flags & STK_ON_RSP)
3334 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3335 else
3336 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 else if (!strcmp(args[0], "stats")) {
3339 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3340 curproxy->uri_auth = NULL; /* we must detach from the default config */
3341
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003342 if (!*args[1]) {
3343 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003344 } else if (!strcmp(args[1], "admin")) {
3345 struct stats_admin_rule *rule;
3346
3347 if (curproxy == &defproxy) {
3348 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352
3353 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3354 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3355 err_code |= ERR_ALERT | ERR_ABORT;
3356 goto out;
3357 }
3358
3359 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3360 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3361 file, linenum, args[0], args[1]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003365 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3366 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3367 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003372 err_code |= warnif_cond_conflicts(cond,
3373 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3374 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003375
3376 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3377 rule->cond = cond;
3378 LIST_INIT(&rule->list);
3379 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 } else if (!strcmp(args[1], "uri")) {
3381 if (*(args[2]) == 0) {
3382 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_ABORT;
3388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
3390 } else if (!strcmp(args[1], "realm")) {
3391 if (*(args[2]) == 0) {
3392 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3396 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_ABORT;
3398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003400 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003401 unsigned interval;
3402
3403 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3404 if (err) {
3405 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3406 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003409 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3410 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003411 err_code |= ERR_ALERT | ERR_ABORT;
3412 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003413 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003414 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003415 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003416
3417 if (curproxy == &defproxy) {
3418 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422
3423 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3424 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3425 err_code |= ERR_ALERT | ERR_ABORT;
3426 goto out;
3427 }
3428
Willy Tarreauff011f22011-01-06 17:51:27 +01003429 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3430 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003431 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3432 file, linenum, args[0]);
3433 err_code |= ERR_WARN;
3434 }
3435
Willy Tarreauff011f22011-01-06 17:51:27 +01003436 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003437
Willy Tarreauff011f22011-01-06 17:51:27 +01003438 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003439 err_code |= ERR_ALERT | ERR_ABORT;
3440 goto out;
3441 }
3442
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003443 err_code |= warnif_cond_conflicts(rule->cond,
3444 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3445 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003446 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003447
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 } else if (!strcmp(args[1], "auth")) {
3449 if (*(args[2]) == 0) {
3450 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003453 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3454 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003455 err_code |= ERR_ALERT | ERR_ABORT;
3456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 }
3458 } else if (!strcmp(args[1], "scope")) {
3459 if (*(args[2]) == 0) {
3460 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003463 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3464 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003465 err_code |= ERR_ALERT | ERR_ABORT;
3466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 }
3468 } else if (!strcmp(args[1], "enable")) {
3469 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_ALERT | ERR_ABORT;
3472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003474 } else if (!strcmp(args[1], "hide-version")) {
3475 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_ABORT;
3478 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003479 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003480 } else if (!strcmp(args[1], "show-legends")) {
3481 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3482 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3483 err_code |= ERR_ALERT | ERR_ABORT;
3484 goto out;
3485 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003486 } else if (!strcmp(args[1], "show-node")) {
3487
3488 if (*args[2]) {
3489 int i;
3490 char c;
3491
3492 for (i=0; args[2][i]; i++) {
3493 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003494 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3495 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003496 break;
3497 }
3498
3499 if (!i || args[2][i]) {
3500 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3501 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3502 file, linenum, args[0], args[1]);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
3506 }
3507
3508 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3509 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3510 err_code |= ERR_ALERT | ERR_ABORT;
3511 goto out;
3512 }
3513 } else if (!strcmp(args[1], "show-desc")) {
3514 char *desc = NULL;
3515
3516 if (*args[2]) {
3517 int i, len=0;
3518 char *d;
3519
Willy Tarreau348acfe2014-04-14 15:00:39 +02003520 for (i = 2; *args[i]; i++)
3521 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003522
3523 desc = d = (char *)calloc(1, len);
3524
Willy Tarreau348acfe2014-04-14 15:00:39 +02003525 d += snprintf(d, desc + len - d, "%s", args[2]);
3526 for (i = 3; *args[i]; i++)
3527 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003528 }
3529
3530 if (!*args[2] && !global.desc)
3531 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3532 file, linenum, args[1]);
3533 else {
3534 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3535 free(desc);
3536 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3537 err_code |= ERR_ALERT | ERR_ABORT;
3538 goto out;
3539 }
3540 free(desc);
3541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003543stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003544 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 +01003545 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 }
3549 }
3550 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003551 int optnum;
3552
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003553 if (*(args[1]) == '\0') {
3554 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003559
3560 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3561 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003562 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3563 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3564 file, linenum, cfg_opts[optnum].name);
3565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
3567 }
Willy Tarreau93893792009-07-23 13:19:11 +02003568 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3569 err_code |= ERR_WARN;
3570 goto out;
3571 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003572
Willy Tarreau3842f002009-06-14 11:39:52 +02003573 curproxy->no_options &= ~cfg_opts[optnum].val;
3574 curproxy->options &= ~cfg_opts[optnum].val;
3575
3576 switch (kwm) {
3577 case KWM_STD:
3578 curproxy->options |= cfg_opts[optnum].val;
3579 break;
3580 case KWM_NO:
3581 curproxy->no_options |= cfg_opts[optnum].val;
3582 break;
3583 case KWM_DEF: /* already cleared */
3584 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003585 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003586
Willy Tarreau93893792009-07-23 13:19:11 +02003587 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003588 }
3589 }
3590
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003591 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3592 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003593 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3594 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3595 file, linenum, cfg_opts2[optnum].name);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
Willy Tarreau93893792009-07-23 13:19:11 +02003599 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3600 err_code |= ERR_WARN;
3601 goto out;
3602 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003603
Willy Tarreau3842f002009-06-14 11:39:52 +02003604 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3605 curproxy->options2 &= ~cfg_opts2[optnum].val;
3606
3607 switch (kwm) {
3608 case KWM_STD:
3609 curproxy->options2 |= cfg_opts2[optnum].val;
3610 break;
3611 case KWM_NO:
3612 curproxy->no_options2 |= cfg_opts2[optnum].val;
3613 break;
3614 case KWM_DEF: /* already cleared */
3615 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003616 }
Willy Tarreau93893792009-07-23 13:19:11 +02003617 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003618 }
3619 }
3620
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003621 /* HTTP options override each other. They can be cancelled using
3622 * "no option xxx" which only switches to default mode if the mode
3623 * was this one (useful for cancelling options set in defaults
3624 * sections).
3625 */
3626 if (strcmp(args[1], "httpclose") == 0) {
3627 if (kwm == KWM_STD) {
3628 curproxy->options &= ~PR_O_HTTP_MODE;
3629 curproxy->options |= PR_O_HTTP_PCL;
3630 goto out;
3631 }
3632 else if (kwm == KWM_NO) {
3633 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3634 curproxy->options &= ~PR_O_HTTP_MODE;
3635 goto out;
3636 }
3637 }
3638 else if (strcmp(args[1], "forceclose") == 0) {
3639 if (kwm == KWM_STD) {
3640 curproxy->options &= ~PR_O_HTTP_MODE;
3641 curproxy->options |= PR_O_HTTP_FCL;
3642 goto out;
3643 }
3644 else if (kwm == KWM_NO) {
3645 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3646 curproxy->options &= ~PR_O_HTTP_MODE;
3647 goto out;
3648 }
3649 }
3650 else if (strcmp(args[1], "http-server-close") == 0) {
3651 if (kwm == KWM_STD) {
3652 curproxy->options &= ~PR_O_HTTP_MODE;
3653 curproxy->options |= PR_O_HTTP_SCL;
3654 goto out;
3655 }
3656 else if (kwm == KWM_NO) {
3657 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3658 curproxy->options &= ~PR_O_HTTP_MODE;
3659 goto out;
3660 }
3661 }
3662 else if (strcmp(args[1], "http-keep-alive") == 0) {
3663 if (kwm == KWM_STD) {
3664 curproxy->options &= ~PR_O_HTTP_MODE;
3665 curproxy->options |= PR_O_HTTP_KAL;
3666 goto out;
3667 }
3668 else if (kwm == KWM_NO) {
3669 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3670 curproxy->options &= ~PR_O_HTTP_MODE;
3671 goto out;
3672 }
3673 }
3674 else if (strcmp(args[1], "http-tunnel") == 0) {
3675 if (kwm == KWM_STD) {
3676 curproxy->options &= ~PR_O_HTTP_MODE;
3677 curproxy->options |= PR_O_HTTP_TUN;
3678 goto out;
3679 }
3680 else if (kwm == KWM_NO) {
3681 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3682 curproxy->options &= ~PR_O_HTTP_MODE;
3683 goto out;
3684 }
3685 }
3686
Willy Tarreau3842f002009-06-14 11:39:52 +02003687 if (kwm != KWM_STD) {
3688 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003689 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003692 }
3693
Emeric Brun3a058f32009-06-30 18:26:00 +02003694 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003695 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003697 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003698 if (*(args[2]) != '\0') {
3699 if (!strcmp(args[2], "clf")) {
3700 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003701 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003702 } else {
3703 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003706 }
3707 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003708 if (curproxy->conf.logformat_string != default_http_log_format &&
3709 curproxy->conf.logformat_string != default_tcp_log_format &&
3710 curproxy->conf.logformat_string != clf_http_log_format)
3711 free(curproxy->conf.logformat_string);
3712 curproxy->conf.logformat_string = logformat;
3713
3714 free(curproxy->conf.lfs_file);
3715 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3716 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003717 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003718 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003720 if (curproxy->conf.logformat_string != default_http_log_format &&
3721 curproxy->conf.logformat_string != default_tcp_log_format &&
3722 curproxy->conf.logformat_string != clf_http_log_format)
3723 free(curproxy->conf.logformat_string);
3724 curproxy->conf.logformat_string = default_tcp_log_format;
3725
3726 free(curproxy->conf.lfs_file);
3727 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3728 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 else if (!strcmp(args[1], "tcpka")) {
3731 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003732 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003734
3735 if (curproxy->cap & PR_CAP_FE)
3736 curproxy->options |= PR_O_TCP_CLI_KA;
3737 if (curproxy->cap & PR_CAP_BE)
3738 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 }
3740 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_WARN;
3743
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003745 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003746 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003747 curproxy->options2 &= ~PR_O2_CHK_ANY;
3748 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003749 if (!*args[2]) { /* no argument */
3750 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3751 curproxy->check_len = strlen(DEF_CHECK_REQ);
3752 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003753 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 curproxy->check_req = (char *)malloc(reqlen);
3755 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003756 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003758 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 if (*args[4])
3760 reqlen += strlen(args[4]);
3761 else
3762 reqlen += strlen("HTTP/1.0");
3763
3764 curproxy->check_req = (char *)malloc(reqlen);
3765 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003766 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003768 }
3769 else if (!strcmp(args[1], "ssl-hello-chk")) {
3770 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003771 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003773
Willy Tarreaua534fea2008-08-03 12:19:50 +02003774 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003775 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003776 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003777 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
Willy Tarreau23677902007-05-08 23:50:35 +02003779 else if (!strcmp(args[1], "smtpchk")) {
3780 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003781 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003782 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003783 curproxy->options2 &= ~PR_O2_CHK_ANY;
3784 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003785
3786 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3787 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3788 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3789 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3790 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3791 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3792 curproxy->check_req = (char *)malloc(reqlen);
3793 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3794 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3795 } else {
3796 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3797 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3798 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3799 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3800 }
3801 }
3802 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003803 else if (!strcmp(args[1], "pgsql-check")) {
3804 /* use PostgreSQL request to check servers' health */
3805 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3806 err_code |= ERR_WARN;
3807
3808 free(curproxy->check_req);
3809 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003810 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003811 curproxy->options2 |= PR_O2_PGSQL_CHK;
3812
3813 if (*(args[2])) {
3814 int cur_arg = 2;
3815
3816 while (*(args[cur_arg])) {
3817 if (strcmp(args[cur_arg], "user") == 0) {
3818 char * packet;
3819 uint32_t packet_len;
3820 uint32_t pv;
3821
3822 /* suboption header - needs additional argument for it */
3823 if (*(args[cur_arg+1]) == 0) {
3824 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3825 file, linenum, args[0], args[1], args[cur_arg]);
3826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
3828 }
3829
3830 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3831 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3832 pv = htonl(0x30000); /* protocol version 3.0 */
3833
3834 packet = (char*) calloc(1, packet_len);
3835
3836 memcpy(packet + 4, &pv, 4);
3837
3838 /* copy "user" */
3839 memcpy(packet + 8, "user", 4);
3840
3841 /* copy username */
3842 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3843
3844 free(curproxy->check_req);
3845 curproxy->check_req = packet;
3846 curproxy->check_len = packet_len;
3847
3848 packet_len = htonl(packet_len);
3849 memcpy(packet, &packet_len, 4);
3850 cur_arg += 2;
3851 } else {
3852 /* unknown suboption - catchall */
3853 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3854 file, linenum, args[0], args[1]);
3855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
3858 } /* end while loop */
3859 }
3860 }
3861
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003862 else if (!strcmp(args[1], "redis-check")) {
3863 /* use REDIS PING request to check servers' health */
3864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3865 err_code |= ERR_WARN;
3866
3867 free(curproxy->check_req);
3868 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003869 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003870 curproxy->options2 |= PR_O2_REDIS_CHK;
3871
3872 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3873 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3874 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3875 }
3876
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003877 else if (!strcmp(args[1], "mysql-check")) {
3878 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003879 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3880 err_code |= ERR_WARN;
3881
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003882 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003883 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003884 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003885 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003886
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003887 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003888 * const char mysql40_client_auth_pkt[] = {
3889 * "\x0e\x00\x00" // packet length
3890 * "\x01" // packet number
3891 * "\x00\x00" // client capabilities
3892 * "\x00\x00\x01" // max packet
3893 * "haproxy\x00" // username (null terminated string)
3894 * "\x00" // filler (always 0x00)
3895 * "\x01\x00\x00" // packet length
3896 * "\x00" // packet number
3897 * "\x01" // COM_QUIT command
3898 * };
3899 */
3900
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003901 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3902 * const char mysql41_client_auth_pkt[] = {
3903 * "\x0e\x00\x00\" // packet length
3904 * "\x01" // packet number
3905 * "\x00\x00\x00\x00" // client capabilities
3906 * "\x00\x00\x00\x01" // max packet
3907 * "\x21" // character set (UTF-8)
3908 * char[23] // All zeroes
3909 * "haproxy\x00" // username (null terminated string)
3910 * "\x00" // filler (always 0x00)
3911 * "\x01\x00\x00" // packet length
3912 * "\x00" // packet number
3913 * "\x01" // COM_QUIT command
3914 * };
3915 */
3916
3917
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003918 if (*(args[2])) {
3919 int cur_arg = 2;
3920
3921 while (*(args[cur_arg])) {
3922 if (strcmp(args[cur_arg], "user") == 0) {
3923 char *mysqluser;
3924 int packetlen, reqlen, userlen;
3925
3926 /* suboption header - needs additional argument for it */
3927 if (*(args[cur_arg+1]) == 0) {
3928 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3929 file, linenum, args[0], args[1], args[cur_arg]);
3930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
3932 }
3933 mysqluser = args[cur_arg + 1];
3934 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003935
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003936 if (*(args[cur_arg+2])) {
3937 if (!strcmp(args[cur_arg+2], "post-41")) {
3938 packetlen = userlen + 7 + 27;
3939 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003940
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003941 free(curproxy->check_req);
3942 curproxy->check_req = (char *)calloc(1, reqlen);
3943 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003944
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003945 snprintf(curproxy->check_req, 4, "%c%c%c",
3946 ((unsigned char) packetlen & 0xff),
3947 ((unsigned char) (packetlen >> 8) & 0xff),
3948 ((unsigned char) (packetlen >> 16) & 0xff));
3949
3950 curproxy->check_req[3] = 1;
3951 curproxy->check_req[5] = 130;
3952 curproxy->check_req[11] = 1;
3953 curproxy->check_req[12] = 33;
3954 memcpy(&curproxy->check_req[36], mysqluser, userlen);
3955 curproxy->check_req[36 + userlen + 1 + 1] = 1;
3956 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
3957 cur_arg += 3;
3958 } else {
3959 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
3960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
3962 }
3963 } else {
3964 packetlen = userlen + 7;
3965 reqlen = packetlen + 9;
3966
3967 free(curproxy->check_req);
3968 curproxy->check_req = (char *)calloc(1, reqlen);
3969 curproxy->check_len = reqlen;
3970
3971 snprintf(curproxy->check_req, 4, "%c%c%c",
3972 ((unsigned char) packetlen & 0xff),
3973 ((unsigned char) (packetlen >> 8) & 0xff),
3974 ((unsigned char) (packetlen >> 16) & 0xff));
3975
3976 curproxy->check_req[3] = 1;
3977 curproxy->check_req[5] = 128;
3978 curproxy->check_req[8] = 1;
3979 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3980 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3981 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3982 cur_arg += 2;
3983 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003984 } else {
3985 /* unknown suboption - catchall */
3986 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3987 file, linenum, args[0], args[1]);
3988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990 }
3991 } /* end while loop */
3992 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003993 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003994 else if (!strcmp(args[1], "ldap-check")) {
3995 /* use LDAP request to check servers' health */
3996 free(curproxy->check_req);
3997 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003998 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003999 curproxy->options2 |= PR_O2_LDAP_CHK;
4000
4001 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4002 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4003 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4004 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004005 else if (!strcmp(args[1], "tcp-check")) {
4006 /* use raw TCPCHK send/expect to check servers' health */
4007 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4008 err_code |= ERR_WARN;
4009
4010 free(curproxy->check_req);
4011 curproxy->check_req = NULL;
4012 curproxy->options2 &= ~PR_O2_CHK_ANY;
4013 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4014 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004015 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004016 int cur_arg;
4017
4018 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4019 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004020 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004021
Willy Tarreau87cf5142011-08-19 22:57:24 +02004022 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004023
4024 free(curproxy->fwdfor_hdr_name);
4025 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4026 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4027
4028 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4029 cur_arg = 2;
4030 while (*(args[cur_arg])) {
4031 if (!strcmp(args[cur_arg], "except")) {
4032 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004033 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004034 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4035 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004038 }
4039 /* flush useless bits */
4040 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004041 cur_arg += 2;
4042 } else if (!strcmp(args[cur_arg], "header")) {
4043 /* suboption header - needs additional argument for it */
4044 if (*(args[cur_arg+1]) == 0) {
4045 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4046 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004049 }
4050 free(curproxy->fwdfor_hdr_name);
4051 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4052 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4053 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004054 } else if (!strcmp(args[cur_arg], "if-none")) {
4055 curproxy->options &= ~PR_O_FF_ALWAYS;
4056 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004057 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004058 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004059 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004060 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004063 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004064 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004065 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004066 else if (!strcmp(args[1], "originalto")) {
4067 int cur_arg;
4068
4069 /* insert x-original-to field, but not for the IP address listed as an except.
4070 * set default options (ie: bitfield, header name, etc)
4071 */
4072
4073 curproxy->options |= PR_O_ORGTO;
4074
4075 free(curproxy->orgto_hdr_name);
4076 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4077 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4078
Willy Tarreau87cf5142011-08-19 22:57:24 +02004079 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004080 cur_arg = 2;
4081 while (*(args[cur_arg])) {
4082 if (!strcmp(args[cur_arg], "except")) {
4083 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004084 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
Maik Broemme2850cb42009-04-17 18:53:21 +02004085 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4086 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004087 err_code |= ERR_ALERT | ERR_FATAL;
4088 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004089 }
4090 /* flush useless bits */
4091 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4092 cur_arg += 2;
4093 } else if (!strcmp(args[cur_arg], "header")) {
4094 /* suboption header - needs additional argument for it */
4095 if (*(args[cur_arg+1]) == 0) {
4096 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4097 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004100 }
4101 free(curproxy->orgto_hdr_name);
4102 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4103 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4104 cur_arg += 2;
4105 } else {
4106 /* unknown suboption - catchall */
4107 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4108 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004111 }
4112 } /* end while loop */
4113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 else {
4115 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118 }
Willy Tarreau93893792009-07-23 13:19:11 +02004119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004121 else if (!strcmp(args[0], "default_backend")) {
4122 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004124
4125 if (*(args[1]) == 0) {
4126 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004129 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004130 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004131 curproxy->defbe.name = strdup(args[1]);
4132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004134 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004136
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004137 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4138 Warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'option redispatch', and will not be supported by future versions.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004139 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 /* enable reconnections to dispatch */
4142 curproxy->options |= PR_O_REDISP;
4143 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004144 else if (!strcmp(args[0], "http-check")) {
4145 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004147
4148 if (strcmp(args[1], "disable-on-404") == 0) {
4149 /* enable a graceful server shutdown on an HTTP 404 response */
4150 curproxy->options |= PR_O_DISABLE404;
4151 }
Willy Tarreauef781042010-01-27 11:53:01 +01004152 else if (strcmp(args[1], "send-state") == 0) {
4153 /* enable emission of the apparent state of a server in HTTP checks */
4154 curproxy->options2 |= PR_O2_CHK_SNDST;
4155 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004156 else if (strcmp(args[1], "expect") == 0) {
4157 const char *ptr_arg;
4158 int cur_arg;
4159
4160 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4161 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165
4166 cur_arg = 2;
4167 /* consider exclamation marks, sole or at the beginning of a word */
4168 while (*(ptr_arg = args[cur_arg])) {
4169 while (*ptr_arg == '!') {
4170 curproxy->options2 ^= PR_O2_EXP_INV;
4171 ptr_arg++;
4172 }
4173 if (*ptr_arg)
4174 break;
4175 cur_arg++;
4176 }
4177 /* now ptr_arg points to the beginning of a word past any possible
4178 * exclamation mark, and cur_arg is the argument which holds this word.
4179 */
4180 if (strcmp(ptr_arg, "status") == 0) {
4181 if (!*(args[cur_arg + 1])) {
4182 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4183 file, linenum, args[0], args[1], ptr_arg);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004188 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004189 curproxy->expect_str = strdup(args[cur_arg + 1]);
4190 }
4191 else if (strcmp(ptr_arg, "string") == 0) {
4192 if (!*(args[cur_arg + 1])) {
4193 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4194 file, linenum, args[0], args[1], ptr_arg);
4195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
4197 }
4198 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004199 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004200 curproxy->expect_str = strdup(args[cur_arg + 1]);
4201 }
4202 else if (strcmp(ptr_arg, "rstatus") == 0) {
4203 if (!*(args[cur_arg + 1])) {
4204 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4205 file, linenum, args[0], args[1], ptr_arg);
4206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
4208 }
4209 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004210 free(curproxy->expect_str);
4211 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4212 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004213 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4214 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4215 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4216 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
4220 }
4221 else if (strcmp(ptr_arg, "rstring") == 0) {
4222 if (!*(args[cur_arg + 1])) {
4223 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4224 file, linenum, args[0], args[1], ptr_arg);
4225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
4227 }
4228 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004229 free(curproxy->expect_str);
4230 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4231 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004232 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4233 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4234 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4235 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
4238 }
4239 }
4240 else {
4241 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4242 file, linenum, args[0], args[1], ptr_arg);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
4245 }
4246 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004247 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004248 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 +02004249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004251 }
4252 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004253 else if (!strcmp(args[0], "tcp-check")) {
4254 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4255 err_code |= ERR_WARN;
4256
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004257 if (strcmp(args[1], "connect") == 0) {
4258 const char *ptr_arg;
4259 int cur_arg;
4260 struct tcpcheck_rule *tcpcheck;
4261 struct list *l;
4262
4263 /* check if first rule is also a 'connect' action */
4264 l = (struct list *)&curproxy->tcpcheck_rules;
4265 if (l->p != l->n) {
4266 tcpcheck = (struct tcpcheck_rule *)l->n;
4267 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4268 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4269 file, linenum);
4270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
4272 }
4273 }
4274
4275 cur_arg = 2;
4276 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4277 tcpcheck->action = TCPCHK_ACT_CONNECT;
4278
4279 /* parsing each parameters to fill up the rule */
4280 while (*(ptr_arg = args[cur_arg])) {
4281 /* tcp port */
4282 if (strcmp(args[cur_arg], "port") == 0) {
4283 if ( (atol(args[cur_arg + 1]) > 65535) ||
4284 (atol(args[cur_arg + 1]) < 1) ){
4285 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4286 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
4289 }
4290 tcpcheck->port = atol(args[cur_arg + 1]);
4291 cur_arg += 2;
4292 }
4293 /* send proxy protocol */
4294 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4295 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4296 cur_arg++;
4297 }
4298#ifdef USE_OPENSSL
4299 else if (strcmp(args[cur_arg], "ssl") == 0) {
4300 curproxy->options |= PR_O_TCPCHK_SSL;
4301 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4302 cur_arg++;
4303 }
4304#endif /* USE_OPENSSL */
4305 else {
4306#ifdef USE_OPENSSL
4307 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4308#else /* USE_OPENSSL */
4309 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4310#endif /* USE_OPENSSL */
4311 file, linenum, args[0], args[1], args[cur_arg]);
4312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
4314 }
4315
4316 }
4317
4318 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4319 }
4320 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004321 if (! *(args[2]) ) {
4322 /* SEND string expected */
4323 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4324 file, linenum, args[0], args[1], args[2]);
4325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
4327 } else {
4328 struct tcpcheck_rule *tcpcheck;
4329
4330 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4331
4332 tcpcheck->action = TCPCHK_ACT_SEND;
4333 tcpcheck->string_len = strlen(args[2]);
4334 tcpcheck->string = strdup(args[2]);
4335 tcpcheck->expect_regex = NULL;
4336
4337 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4338 }
4339 }
4340 else if (strcmp(args[1], "send-binary") == 0) {
4341 if (! *(args[2]) ) {
4342 /* SEND binary string expected */
4343 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4344 file, linenum, args[0], args[1], args[2]);
4345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
4347 } else {
4348 struct tcpcheck_rule *tcpcheck;
4349 char *err = NULL;
4350
4351 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4352
4353 tcpcheck->action = TCPCHK_ACT_SEND;
4354 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4355 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4356 file, linenum, args[0], args[1], args[2], err);
4357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360 tcpcheck->expect_regex = NULL;
4361
4362 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4363 }
4364 }
4365 else if (strcmp(args[1], "expect") == 0) {
4366 const char *ptr_arg;
4367 int cur_arg;
4368 int inverse = 0;
4369
4370 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4371 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375
4376 cur_arg = 2;
4377 /* consider exclamation marks, sole or at the beginning of a word */
4378 while (*(ptr_arg = args[cur_arg])) {
4379 while (*ptr_arg == '!') {
4380 inverse = !inverse;
4381 ptr_arg++;
4382 }
4383 if (*ptr_arg)
4384 break;
4385 cur_arg++;
4386 }
4387 /* now ptr_arg points to the beginning of a word past any possible
4388 * exclamation mark, and cur_arg is the argument which holds this word.
4389 */
4390 if (strcmp(ptr_arg, "binary") == 0) {
4391 if (!*(args[cur_arg + 1])) {
4392 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4393 file, linenum, args[0], args[1], ptr_arg);
4394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
4396 }
4397 struct tcpcheck_rule *tcpcheck;
4398 char *err = NULL;
4399
4400 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4401
4402 tcpcheck->action = TCPCHK_ACT_EXPECT;
4403 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4404 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4405 file, linenum, args[0], args[1], args[2], err);
4406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
4408 }
4409 tcpcheck->expect_regex = NULL;
4410 tcpcheck->inverse = inverse;
4411
4412 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4413 }
4414 else if (strcmp(ptr_arg, "string") == 0) {
4415 if (!*(args[cur_arg + 1])) {
4416 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4417 file, linenum, args[0], args[1], ptr_arg);
4418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
4420 }
4421 struct tcpcheck_rule *tcpcheck;
4422
4423 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4424
4425 tcpcheck->action = TCPCHK_ACT_EXPECT;
4426 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4427 tcpcheck->string = strdup(args[cur_arg + 1]);
4428 tcpcheck->expect_regex = NULL;
4429 tcpcheck->inverse = inverse;
4430
4431 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4432 }
4433 else if (strcmp(ptr_arg, "rstring") == 0) {
4434 if (!*(args[cur_arg + 1])) {
4435 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4436 file, linenum, args[0], args[1], ptr_arg);
4437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
4439 }
4440 struct tcpcheck_rule *tcpcheck;
4441
4442 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4443
4444 tcpcheck->action = TCPCHK_ACT_EXPECT;
4445 tcpcheck->string_len = 0;
4446 tcpcheck->string = NULL;
4447 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4448 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4449 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4450 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
4453 }
4454 tcpcheck->inverse = inverse;
4455
4456 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4457 }
4458 else {
4459 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4460 file, linenum, args[0], args[1], ptr_arg);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
4464 }
4465 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004466 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
4470 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004471 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004472 if (curproxy == &defproxy) {
4473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004476 }
4477
Willy Tarreaub80c2302007-11-30 20:51:32 +01004478 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004479 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004480
4481 if (strcmp(args[1], "fail") == 0) {
4482 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004483 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004484 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4485 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004488 }
4489
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004490 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4491 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4492 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004495 }
4496 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4497 }
4498 else {
4499 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004502 }
4503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504#ifdef TPROXY
4505 else if (!strcmp(args[0], "transparent")) {
4506 /* enable transparent proxy connections */
4507 curproxy->options |= PR_O_TRANSP;
4508 }
4509#endif
4510 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004511 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004513
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 if (*(args[1]) == 0) {
4515 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
4519 curproxy->maxconn = atol(args[1]);
4520 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004521 else if (!strcmp(args[0], "backlog")) { /* backlog */
4522 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004523 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004524
4525 if (*(args[1]) == 0) {
4526 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004529 }
4530 curproxy->backlog = atol(args[1]);
4531 }
Willy Tarreau86034312006-12-29 00:10:33 +01004532 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004533 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004534 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004535
Willy Tarreau86034312006-12-29 00:10:33 +01004536 if (*(args[1]) == 0) {
4537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004540 }
4541 curproxy->fullconn = atol(args[1]);
4542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4544 if (*(args[1]) == 0) {
4545 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004549 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4550 if (err) {
4551 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4552 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004555 }
4556 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 }
4558 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004559 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004560 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004561 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004562
Willy Tarreaubaaee002006-06-26 02:48:02 +02004563 if (curproxy == &defproxy) {
4564 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004568 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004569 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004570
Willy Tarreau902636f2013-03-10 19:44:48 +01004571 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004572 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004573 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004574 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004575 goto out;
4576 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004577
4578 proto = protocol_by_family(sk->ss_family);
4579 if (!proto || !proto->connect) {
4580 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4581 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
4584 }
4585
4586 if (port1 != port2) {
4587 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4588 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004592
4593 if (!port1) {
4594 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4595 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
4598 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004599
Willy Tarreaud5191e72010-02-09 20:50:45 +01004600 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004601 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 }
4603 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004604 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004606
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004607 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4608 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_ALERT | ERR_FATAL;
4610 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004613 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004614 /**
4615 * The syntax for hash-type config element is
4616 * hash-type {map-based|consistent} [[<algo>] avalanche]
4617 *
4618 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4619 */
4620 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004621
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004622 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4623 err_code |= ERR_WARN;
4624
4625 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004626 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4627 }
4628 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004629 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4630 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004631 else if (strcmp(args[1], "avalanche") == 0) {
4632 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]);
4633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004635 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004636 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004637 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
4640 }
Bhaskar98634f02013-10-29 23:30:51 -04004641
4642 /* set the hash function to use */
4643 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004644 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004645 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004646
4647 /* if consistent with no argument, then avalanche modifier is also applied */
4648 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4649 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004650 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004651 /* set the hash function */
4652 if (!strcmp(args[2], "sdbm")) {
4653 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4654 }
4655 else if (!strcmp(args[2], "djb2")) {
4656 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004657 } else if (!strcmp(args[2], "wt6")) {
4658 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004659 }
4660 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004661 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 -05004662 err_code |= ERR_ALERT | ERR_FATAL;
4663 goto out;
4664 }
4665
4666 /* set the hash modifier */
4667 if (!strcmp(args[3], "avalanche")) {
4668 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4669 }
4670 else if (*args[3]) {
4671 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004675 }
William Lallemanda73203e2012-03-12 12:48:57 +01004676 }
William Lallemanda73203e2012-03-12 12:48:57 +01004677 else if (strcmp(args[0], "unique-id-format") == 0) {
4678 if (!*(args[1])) {
4679 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
William Lallemand3203ff42012-11-11 17:30:56 +01004683 if (*(args[2])) {
4684 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004688 free(curproxy->conf.uniqueid_format_string);
4689 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004690
Willy Tarreau62a61232013-04-12 18:13:46 +02004691 free(curproxy->conf.uif_file);
4692 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4693 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004694 }
William Lallemanda73203e2012-03-12 12:48:57 +01004695
4696 else if (strcmp(args[0], "unique-id-header") == 0) {
4697 if (!*(args[1])) {
4698 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701 }
4702 free(curproxy->header_unique_id);
4703 curproxy->header_unique_id = strdup(args[1]);
4704 }
4705
William Lallemand723b73a2012-02-08 16:37:49 +01004706 else if (strcmp(args[0], "log-format") == 0) {
4707 if (!*(args[1])) {
4708 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
4711 }
William Lallemand3203ff42012-11-11 17:30:56 +01004712 if (*(args[2])) {
4713 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004717
Willy Tarreau62a61232013-04-12 18:13:46 +02004718 if (curproxy->conf.logformat_string != default_http_log_format &&
4719 curproxy->conf.logformat_string != default_tcp_log_format &&
4720 curproxy->conf.logformat_string != clf_http_log_format)
4721 free(curproxy->conf.logformat_string);
4722 curproxy->conf.logformat_string = strdup(args[1]);
4723
4724 free(curproxy->conf.lfs_file);
4725 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4726 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004727
4728 /* get a chance to improve log-format error reporting by
4729 * reporting the correct line-number when possible.
4730 */
4731 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4732 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4733 file, linenum, curproxy->id);
4734 err_code |= ERR_WARN;
4735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 }
William Lallemand723b73a2012-02-08 16:37:49 +01004737
William Lallemand0f99e342011-10-12 17:50:54 +02004738 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4739 /* delete previous herited or defined syslog servers */
4740 struct logsrv *back;
4741
4742 if (*(args[1]) != 0) {
4743 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
4746 }
4747
William Lallemand723b73a2012-02-08 16:37:49 +01004748 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4749 LIST_DEL(&tmplogsrv->list);
4750 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004751 }
4752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004754 struct logsrv *logsrv;
4755
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004757 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004758 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004759 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004760 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004761 LIST_INIT(&node->list);
4762 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
4765 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004766 struct sockaddr_storage *sk;
4767 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004768
4769 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770
William Lallemand0f99e342011-10-12 17:50:54 +02004771 logsrv->facility = get_log_facility(args[2]);
4772 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
4778
William Lallemand0f99e342011-10-12 17:50:54 +02004779 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004781 logsrv->level = get_log_level(args[3]);
4782 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
4788 }
4789
William Lallemand0f99e342011-10-12 17:50:54 +02004790 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004791 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004792 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004793 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004794 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
4797
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004798 }
4799 }
4800
Willy Tarreau902636f2013-03-10 19:44:48 +01004801 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004802 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004803 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004804 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004805 goto out;
4806 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004807
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004808 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004809
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004810 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004811 if (port1 != port2) {
4812 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4813 file, linenum, args[0], args[1]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
4817
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004818 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004819 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
William Lallemand0f99e342011-10-12 17:50:54 +02004821
4822 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 }
4824 else {
4825 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4826 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 }
4830 }
4831 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004832 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004833 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004834 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004835 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004836
Willy Tarreau977b8e42006-12-29 14:19:17 +01004837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004838 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004839
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004841 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4842 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004846
4847 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004848 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4849 free(curproxy->conn_src.iface_name);
4850 curproxy->conn_src.iface_name = NULL;
4851 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004852
Willy Tarreau902636f2013-03-10 19:44:48 +01004853 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004854 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004855 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004856 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004857 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004858 goto out;
4859 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004860
4861 proto = protocol_by_family(sk->ss_family);
4862 if (!proto || !proto->connect) {
4863 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004864 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004868
4869 if (port1 != port2) {
4870 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4871 file, linenum, args[0], args[1]);
4872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
4874 }
4875
Willy Tarreauef9a3602012-12-08 22:29:20 +01004876 curproxy->conn_src.source_addr = *sk;
4877 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004878
4879 cur_arg = 2;
4880 while (*(args[cur_arg])) {
4881 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004882#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4883#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02004884 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004885 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4886 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004889 }
4890#endif
4891 if (!*args[cur_arg + 1]) {
4892 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4893 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004896 }
4897
4898 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004899 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4900 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004901 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004902 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4903 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004904 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4905 char *name, *end;
4906
4907 name = args[cur_arg+1] + 7;
4908 while (isspace(*name))
4909 name++;
4910
4911 end = name;
4912 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4913 end++;
4914
Willy Tarreauef9a3602012-12-08 22:29:20 +01004915 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4916 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4917 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4918 curproxy->conn_src.bind_hdr_len = end - name;
4919 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4920 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4921 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004922
4923 /* now look for an occurrence number */
4924 while (isspace(*end))
4925 end++;
4926 if (*end == ',') {
4927 end++;
4928 name = end;
4929 if (*end == '-')
4930 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004931 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004932 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004933 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004934 }
4935
Willy Tarreauef9a3602012-12-08 22:29:20 +01004936 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004937 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4938 " occurrences values smaller than %d.\n",
4939 file, linenum, MAX_HDR_HISTORY);
4940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004943 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004944 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004945
Willy Tarreau902636f2013-03-10 19:44:48 +01004946 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004947 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004948 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004949 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004950 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004951 goto out;
4952 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004953
4954 proto = protocol_by_family(sk->ss_family);
4955 if (!proto || !proto->connect) {
4956 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4957 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
4960 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004961
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004962 if (port1 != port2) {
4963 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4964 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
4967 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004968 curproxy->conn_src.tproxy_addr = *sk;
4969 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004970 }
4971 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004972#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004973 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004974#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004975#else /* no TPROXY support */
4976 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004977 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004980#endif
4981 cur_arg += 2;
4982 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004983 }
4984
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004985 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4986#ifdef SO_BINDTODEVICE
4987 if (!*args[cur_arg + 1]) {
4988 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4989 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004992 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004993 free(curproxy->conn_src.iface_name);
4994 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4995 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004996 global.last_checks |= LSTCHK_NETADM;
4997#else
4998 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4999 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005002#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005003 cur_arg += 2;
5004 continue;
5005 }
5006 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005007 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005012 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5013 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5014 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025
5026 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005027 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005028 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
5032 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005034 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005035 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 }
5039 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005040 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005041 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005042 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
5046 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005047 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005048 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005049 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 }
5053 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005054 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005055 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005056 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005057 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005060 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005062 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005063 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005065 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005066 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005067 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005068 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005069 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005070 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005072 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005073
5074 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5075 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005076 }
5077 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005079 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005080 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005081 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005082 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005083
5084 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5085 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005088 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5090 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094
5095 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005096 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005097 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005098 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 }
5101 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005102 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005103 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005104 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 }
5108 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005110 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005111 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005112 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
5115 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005117 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005118 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
5122 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005124 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005125 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005129 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005131 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005132 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005134 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005137 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005138
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 if (curproxy == &defproxy) {
5140 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005144 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 if (*(args[1]) == 0) {
5148 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005152
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005153 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005154 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5155 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5156 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005160 err_code |= warnif_cond_conflicts(cond,
5161 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5162 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005163 }
5164 else if (*args[2]) {
5165 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5166 file, linenum, args[0], args[2]);
5167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
5169 }
5170
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005171 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005172 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005173 wl->s = strdup(args[1]);
5174 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005175 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
5177 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005184
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005186 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005187 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 }
5191 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005193 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005194 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
5198 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005200 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005201 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 }
5205 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005207 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5208 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005209 err_code |= ERR_ALERT | ERR_FATAL;
5210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 }
5212
Willy Tarreauade5ec42010-01-28 19:33:49 +01005213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005214 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005215 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 }
5219 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005221 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005222 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005223 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
5226 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005228 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005229 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005230 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
5233 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005234 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005235
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 if (curproxy == &defproxy) {
5237 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005241 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005242 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 if (*(args[1]) == 0) {
5245 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
5249
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005250 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005251 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5252 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5253 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005254 err_code |= ERR_ALERT | ERR_FATAL;
5255 goto out;
5256 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005257 err_code |= warnif_cond_conflicts(cond,
5258 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5259 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005260 }
5261 else if (*args[2]) {
5262 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5263 file, linenum, args[0], args[2]);
5264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
5266 }
5267
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005268 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005269 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005270 wl->s = strdup(args[1]);
5271 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 else if (!strcmp(args[0], "errorloc") ||
5274 !strcmp(args[0], "errorloc302") ||
5275 !strcmp(args[0], "errorloc303")) { /* error location */
5276 int errnum, errlen;
5277 char *err;
5278
Willy Tarreau977b8e42006-12-29 14:19:17 +01005279 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005280 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005281
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005283 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005284 err_code |= ERR_ALERT | ERR_FATAL;
5285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
5287
5288 errnum = atol(args[1]);
5289 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005290 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5291 err = malloc(errlen);
5292 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005294 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5295 err = malloc(errlen);
5296 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 }
5298
Willy Tarreau0f772532006-12-23 20:51:41 +01005299 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5300 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005301 chunk_destroy(&curproxy->errmsg[rc]);
5302 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005303 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005306
5307 if (rc >= HTTP_ERR_SIZE) {
5308 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5309 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 free(err);
5311 }
5312 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005313 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5314 int errnum, errlen, fd;
5315 char *err;
5316 struct stat stat;
5317
5318 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005319 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005320
5321 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005322 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005325 }
5326
5327 fd = open(args[2], O_RDONLY);
5328 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5329 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5330 file, linenum, args[2], args[1]);
5331 if (fd >= 0)
5332 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005335 }
5336
Willy Tarreau27a674e2009-08-17 07:23:33 +02005337 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005338 errlen = stat.st_size;
5339 } else {
5340 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005341 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005342 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005343 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005344 }
5345
5346 err = malloc(errlen); /* malloc() must succeed during parsing */
5347 errnum = read(fd, err, errlen);
5348 if (errnum != errlen) {
5349 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5350 file, linenum, args[2], args[1]);
5351 close(fd);
5352 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005355 }
5356 close(fd);
5357
5358 errnum = atol(args[1]);
5359 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5360 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005361 chunk_destroy(&curproxy->errmsg[rc]);
5362 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005363 break;
5364 }
5365 }
5366
5367 if (rc >= HTTP_ERR_SIZE) {
5368 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5369 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005370 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005371 free(err);
5372 }
5373 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005374 else if (!strcmp(args[0], "compression")) {
5375 struct comp *comp;
5376 if (curproxy->comp == NULL) {
5377 comp = calloc(1, sizeof(struct comp));
5378 curproxy->comp = comp;
5379 } else {
5380 comp = curproxy->comp;
5381 }
5382
5383 if (!strcmp(args[1], "algo")) {
5384 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005385 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005386
William Lallemand82fe75c2012-10-23 10:25:10 +02005387 cur_arg = 2;
5388 if (!*args[cur_arg]) {
5389 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5390 file, linenum, args[0]);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
5393 }
5394 while (*(args[cur_arg])) {
5395 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5396 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5397 file, linenum, args[0], args[cur_arg]);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
William Lallemand552df672012-11-07 13:21:47 +01005401 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5402 curproxy->comp->algos->end(&ctx);
5403 } else {
5404 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5405 file, linenum, args[0], args[cur_arg]);
5406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005409 cur_arg ++;
5410 continue;
5411 }
5412 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005413 else if (!strcmp(args[1], "offload")) {
5414 comp->offload = 1;
5415 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005416 else if (!strcmp(args[1], "type")) {
5417 int cur_arg;
5418 cur_arg = 2;
5419 if (!*args[cur_arg]) {
5420 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5421 file, linenum, args[0]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425 while (*(args[cur_arg])) {
5426 comp_append_type(comp, args[cur_arg]);
5427 cur_arg ++;
5428 continue;
5429 }
5430 }
5431 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005432 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005433 file, linenum, args[0]);
5434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
5437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005439 struct cfg_kw_list *kwl;
5440 int index;
5441
5442 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5443 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5444 if (kwl->kw[index].section != CFG_LISTEN)
5445 continue;
5446 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5447 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005448 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005449 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005450 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005453 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005454 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005455 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005456 err_code |= ERR_WARN;
5457 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005458 }
Willy Tarreau93893792009-07-23 13:19:11 +02005459 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005460 }
5461 }
5462 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005463
Willy Tarreau6daf3432008-01-22 16:44:08 +01005464 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 }
Willy Tarreau93893792009-07-23 13:19:11 +02005468 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005469 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005470 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471}
5472
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005473int
5474cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5475{
5476
5477 int err_code = 0;
5478 const char *err;
5479
5480 if (!strcmp(args[0], "userlist")) { /* new userlist */
5481 struct userlist *newul;
5482
5483 if (!*args[1]) {
5484 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5485 file, linenum, args[0]);
5486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 }
5489
5490 err = invalid_char(args[1]);
5491 if (err) {
5492 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5493 file, linenum, *err, args[0], args[1]);
5494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
5496 }
5497
5498 for (newul = userlist; newul; newul = newul->next)
5499 if (!strcmp(newul->name, args[1])) {
5500 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5501 file, linenum, args[1]);
5502 err_code |= ERR_WARN;
5503 goto out;
5504 }
5505
5506 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5507 if (!newul) {
5508 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5509 err_code |= ERR_ALERT | ERR_ABORT;
5510 goto out;
5511 }
5512
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005513 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005514 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005515 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5516 err_code |= ERR_ALERT | ERR_ABORT;
5517 goto out;
5518 }
5519
5520 newul->next = userlist;
5521 userlist = newul;
5522
5523 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005524 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005525 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005526 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005527
5528 if (!*args[1]) {
5529 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5530 file, linenum, args[0]);
5531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 }
5534
5535 err = invalid_char(args[1]);
5536 if (err) {
5537 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5538 file, linenum, *err, args[0], args[1]);
5539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
5542
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005543 for (ag = userlist->groups; ag; ag = ag->next)
5544 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005545 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5546 file, linenum, args[1], userlist->name);
5547 err_code |= ERR_ALERT;
5548 goto out;
5549 }
5550
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005551 ag = calloc(1, sizeof(*ag));
5552 if (!ag) {
5553 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5554 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005555 goto out;
5556 }
5557
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005558 ag->name = strdup(args[1]);
5559 if (!ag) {
5560 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5561 err_code |= ERR_ALERT | ERR_ABORT;
5562 goto out;
5563 }
5564
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005565 cur_arg = 2;
5566
5567 while (*args[cur_arg]) {
5568 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005569 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005570 cur_arg += 2;
5571 continue;
5572 } else {
5573 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5574 file, linenum, args[0]);
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
5577 }
5578 }
5579
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005580 ag->next = userlist->groups;
5581 userlist->groups = ag;
5582
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005583 } else if (!strcmp(args[0], "user")) { /* new user */
5584 struct auth_users *newuser;
5585 int cur_arg;
5586
5587 if (!*args[1]) {
5588 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5589 file, linenum, args[0]);
5590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
5592 }
5593
5594 for (newuser = userlist->users; newuser; newuser = newuser->next)
5595 if (!strcmp(newuser->user, args[1])) {
5596 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5597 file, linenum, args[1], userlist->name);
5598 err_code |= ERR_ALERT;
5599 goto out;
5600 }
5601
5602 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5603 if (!newuser) {
5604 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5605 err_code |= ERR_ALERT | ERR_ABORT;
5606 goto out;
5607 }
5608
5609 newuser->user = strdup(args[1]);
5610
5611 newuser->next = userlist->users;
5612 userlist->users = newuser;
5613
5614 cur_arg = 2;
5615
5616 while (*args[cur_arg]) {
5617 if (!strcmp(args[cur_arg], "password")) {
5618#ifndef CONFIG_HAP_CRYPT
5619 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5620 file, linenum);
5621 err_code |= ERR_ALERT;
5622#endif
5623 newuser->pass = strdup(args[cur_arg + 1]);
5624 cur_arg += 2;
5625 continue;
5626 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5627 newuser->pass = strdup(args[cur_arg + 1]);
5628 newuser->flags |= AU_O_INSECURE;
5629 cur_arg += 2;
5630 continue;
5631 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005632 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005633 cur_arg += 2;
5634 continue;
5635 } else {
5636 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5637 file, linenum, args[0]);
5638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
5640 }
5641 }
5642 } else {
5643 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5644 err_code |= ERR_ALERT | ERR_FATAL;
5645 }
5646
5647out:
5648 return err_code;
5649}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650
5651/*
5652 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005653 * Returns the error code, 0 if OK, or any combination of :
5654 * - ERR_ABORT: must abort ASAP
5655 * - ERR_FATAL: we can continue parsing but not start the service
5656 * - ERR_WARN: a warning has been emitted
5657 * - ERR_ALERT: an alert has been emitted
5658 * Only the two first ones can stop processing, the two others are just
5659 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005661int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005663 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 FILE *f;
5665 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005666 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005667 struct cfg_section *cs = NULL;
5668 struct cfg_section *ics;
5669
5670 /* Register internal sections */
5671 if (!cfg_register_section("listen", cfg_parse_listen) ||
5672 !cfg_register_section("frontend", cfg_parse_listen) ||
5673 !cfg_register_section("backend", cfg_parse_listen) ||
5674 !cfg_register_section("ruleset", cfg_parse_listen) ||
5675 !cfg_register_section("defaults", cfg_parse_listen) ||
5676 !cfg_register_section("global", cfg_parse_global) ||
5677 !cfg_register_section("userlist", cfg_parse_users) ||
5678 !cfg_register_section("peers", cfg_parse_peers))
5679 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 if ((f=fopen(file,"r")) == NULL)
5682 return -1;
5683
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005684 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005685 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005686 char *end;
5687 char *args[MAX_LINE_ARGS + 1];
5688 char *line = thisline;
5689
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690 linenum++;
5691
5692 end = line + strlen(line);
5693
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005694 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5695 /* Check if we reached the limit and the last char is not \n.
5696 * Watch out for the last line without the terminating '\n'!
5697 */
5698 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005699 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005700 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005701 }
5702
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005704 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 line++;
5706
5707 arg = 0;
5708 args[arg] = line;
5709
5710 while (*line && arg < MAX_LINE_ARGS) {
5711 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5712 * C equivalent value. Other combinations left unchanged (eg: \1).
5713 */
5714 if (*line == '\\') {
5715 int skip = 0;
5716 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5717 *line = line[1];
5718 skip = 1;
5719 }
5720 else if (line[1] == 'r') {
5721 *line = '\r';
5722 skip = 1;
5723 }
5724 else if (line[1] == 'n') {
5725 *line = '\n';
5726 skip = 1;
5727 }
5728 else if (line[1] == 't') {
5729 *line = '\t';
5730 skip = 1;
5731 }
5732 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005733 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 unsigned char hex1, hex2;
5735 hex1 = toupper(line[2]) - '0';
5736 hex2 = toupper(line[3]) - '0';
5737 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5738 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5739 *line = (hex1<<4) + hex2;
5740 skip = 3;
5741 }
5742 else {
5743 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005744 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 }
5746 }
5747 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005748 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 end -= skip;
5750 }
5751 line++;
5752 }
5753 else if (*line == '#' || *line == '\n' || *line == '\r') {
5754 /* end of string, end of loop */
5755 *line = 0;
5756 break;
5757 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005758 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005760 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005761 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 line++;
5763 args[++arg] = line;
5764 }
5765 else {
5766 line++;
5767 }
5768 }
5769
5770 /* empty line */
5771 if (!**args)
5772 continue;
5773
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005774 if (*line) {
5775 /* we had to stop due to too many args.
5776 * Let's terminate the string, print the offending part then cut the
5777 * last arg.
5778 */
5779 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5780 line++;
5781 *line = '\0';
5782
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005783 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005784 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 args[arg] = line;
5787 }
5788
Willy Tarreau540abe42007-05-02 20:50:16 +02005789 /* zero out remaining args and ensure that at least one entry
5790 * is zeroed out.
5791 */
5792 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 args[arg] = line;
5794 }
5795
Willy Tarreau3842f002009-06-14 11:39:52 +02005796 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005797 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005798 char *tmp;
5799
Willy Tarreau3842f002009-06-14 11:39:52 +02005800 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005801 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005802 for (arg=0; *args[arg+1]; arg++)
5803 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005804 *tmp = '\0'; // fix the next arg to \0
5805 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005806 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005807 else if (!strcmp(args[0], "default")) {
5808 kwm = KWM_DEF;
5809 for (arg=0; *args[arg+1]; arg++)
5810 args[arg] = args[arg+1]; // shift args after inversion
5811 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005812
William Lallemand0f99e342011-10-12 17:50:54 +02005813 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5814 strcmp(args[0], "log") != 0) {
5815 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005816 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005817 }
5818
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005819 /* detect section start */
5820 list_for_each_entry(ics, &sections, list) {
5821 if (strcmp(args[0], ics->section_name) == 0) {
5822 cursection = ics->section_name;
5823 cs = ics;
5824 break;
5825 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005826 }
5827
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005829 if (cs)
5830 err_code |= cs->section_parser(file, linenum, args, kwm);
5831 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005832 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005833 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005835
5836 if (err_code & ERR_ABORT)
5837 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005839 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005841 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005842}
5843
Willy Tarreaubb925012009-07-23 13:36:36 +02005844/*
5845 * Returns the error code, 0 if OK, or any combination of :
5846 * - ERR_ABORT: must abort ASAP
5847 * - ERR_FATAL: we can continue parsing but not start the service
5848 * - ERR_WARN: a warning has been emitted
5849 * - ERR_ALERT: an alert has been emitted
5850 * Only the two first ones can stop processing, the two others are just
5851 * indicators.
5852 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005853int check_config_validity()
5854{
5855 int cfgerr = 0;
5856 struct proxy *curproxy = NULL;
5857 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005858 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005859 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005860 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005862 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 /*
5864 * Now, check for the integrity of all that we have collected.
5865 */
5866
5867 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005868 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869
Willy Tarreau193b8c62012-11-22 00:17:38 +01005870 if (!global.tune.max_http_hdr)
5871 global.tune.max_http_hdr = MAX_HTTP_HDR;
5872
5873 if (!global.tune.cookie_len)
5874 global.tune.cookie_len = CAPTURE_LEN;
5875
5876 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5877
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005878 /* Post initialisation of the users and groups lists. */
5879 err_code = userlist_postinit();
5880 if (err_code != ERR_NONE)
5881 goto out;
5882
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005883 /* first, we will invert the proxy list order */
5884 curproxy = NULL;
5885 while (proxy) {
5886 struct proxy *next;
5887
5888 next = proxy->next;
5889 proxy->next = curproxy;
5890 curproxy = proxy;
5891 if (!next)
5892 break;
5893 proxy = next;
5894 }
5895
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005897 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005898 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005899 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005900 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005901 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005902 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005903 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005904
Willy Tarreau050536d2012-10-04 08:47:34 +02005905 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005906 /* proxy ID not set, use automatic numbering with first
5907 * spare entry starting with next_pxid.
5908 */
5909 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5910 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5911 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005912 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005913 next_pxid++;
5914
Willy Tarreau55ea7572007-06-17 19:56:27 +02005915
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005917 /* ensure we don't keep listeners uselessly bound */
5918 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 curproxy = curproxy->next;
5920 continue;
5921 }
5922
Willy Tarreau102df612014-05-07 23:56:38 +02005923 /* Check multi-process mode compatibility for the current proxy */
5924
5925 if (curproxy->bind_proc) {
5926 /* an explicit bind-process was specified, let's check how many
5927 * processes remain.
5928 */
5929 nbproc = popcount(curproxy->bind_proc);
5930
5931 curproxy->bind_proc &= nbits(global.nbproc);
5932 if (!curproxy->bind_proc && nbproc == 1) {
5933 Warning("Proxy '%s': the process specified on the 'bind-process' directive refers to a process number that is higher than global.nbproc. The proxy has been forced to run on process 1 only.\n", curproxy->id);
5934 curproxy->bind_proc = 1;
5935 }
5936 else if (!curproxy->bind_proc && nbproc > 1) {
5937 Warning("Proxy '%s': all processes specified on the 'bind-process' directive refer to numbers that are all higher than global.nbproc. The directive was ignored and the proxy will run on all processes.\n", curproxy->id);
5938 curproxy->bind_proc = 0;
5939 }
5940 }
5941
Willy Tarreau3d209582014-05-09 17:06:11 +02005942 /* check and reduce the bind-proc of each listener */
5943 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
5944 unsigned long mask;
5945
5946 if (!bind_conf->bind_proc)
5947 continue;
5948
5949 mask = nbits(global.nbproc);
5950 if (curproxy->bind_proc)
5951 mask &= curproxy->bind_proc;
5952 /* mask cannot be null here thanks to the previous checks */
5953
5954 nbproc = popcount(bind_conf->bind_proc);
5955 bind_conf->bind_proc &= mask;
5956
5957 if (!bind_conf->bind_proc && nbproc == 1) {
5958 Warning("Proxy '%s': the process number specified on the 'process' directive of 'bind %s' at [%s:%d] refers to a process not covered by the proxy. This has been fixed by forcing it to run on the proxy's first process only.\n",
5959 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5960 bind_conf->bind_proc = mask & ~(mask - 1);
5961 }
5962 else if (!bind_conf->bind_proc && nbproc > 1) {
5963 Warning("Proxy '%s': the process range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to processes not covered by the proxy. The directive was ignored so that all of the proxy's processes are used.\n",
5964 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5965 bind_conf->bind_proc = 0;
5966 }
5967 }
5968
Willy Tarreau102df612014-05-07 23:56:38 +02005969 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
5970 * We now check how many processes the proxy will effectively run on.
5971 */
5972
5973 nbproc = global.nbproc;
5974 if (curproxy->bind_proc)
5975 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
5976
5977 if (global.nbproc > 1 && curproxy->table.peers.name) {
5978 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
5979 curproxy->id);
5980 cfgerr++;
5981 }
Willy Tarreau16a21472012-11-19 12:39:59 +01005982
Willy Tarreauff01a212009-03-15 13:46:16 +01005983 switch (curproxy->mode) {
5984 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005985 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005986 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005987 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5988 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005989 cfgerr++;
5990 }
5991
5992 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005993 Warning("config : servers will be ignored for %s '%s'.\n",
5994 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005995 break;
5996
5997 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005998 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005999 break;
6000
6001 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006002 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006003 break;
6004 }
6005
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006006 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006007 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006008 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006009 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6010 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006011 cfgerr++;
6012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006013#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006014 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006015 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6016 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006017 cfgerr++;
6018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006020 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006021 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6022 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006023 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006024 }
6025 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006026 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006027 /* If no LB algo is set in a backend, and we're not in
6028 * transparent mode, dispatch mode nor proxy mode, we
6029 * want to use balance roundrobin by default.
6030 */
6031 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6032 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 }
6034 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006035
Willy Tarreau1620ec32011-08-06 17:05:02 +02006036 if (curproxy->options & PR_O_DISPATCH)
6037 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6038 else if (curproxy->options & PR_O_HTTP_PROXY)
6039 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6040 else if (curproxy->options & PR_O_TRANSP)
6041 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006042
Willy Tarreau1620ec32011-08-06 17:05:02 +02006043 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6044 if (curproxy->options & PR_O_DISABLE404) {
6045 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6046 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6047 err_code |= ERR_WARN;
6048 curproxy->options &= ~PR_O_DISABLE404;
6049 }
6050 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6051 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6052 "send-state", proxy_type_str(curproxy), curproxy->id);
6053 err_code |= ERR_WARN;
6054 curproxy->options &= ~PR_O2_CHK_SNDST;
6055 }
Willy Tarreauef781042010-01-27 11:53:01 +01006056 }
6057
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006058 /* if a default backend was specified, let's find it */
6059 if (curproxy->defbe.name) {
6060 struct proxy *target;
6061
Alex Williams96532db2009-11-01 21:27:13 -05006062 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006063 if (!target) {
6064 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6065 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006066 cfgerr++;
6067 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006068 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6069 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006070 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006071 } else {
6072 free(curproxy->defbe.name);
6073 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006074 /* we force the backend to be present on at least all of
6075 * the frontend's processes.
6076 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006077 if (target->bind_proc)
6078 target->bind_proc = curproxy->bind_proc ?
6079 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006080
6081 /* Emit a warning if this proxy also has some servers */
6082 if (curproxy->srv) {
6083 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6084 curproxy->id);
6085 err_code |= ERR_WARN;
6086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006087 }
6088 }
6089
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006090 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006091 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6092 /* map jump target for ACT_SETBE in req_rep chain */
6093 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006094 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006095 struct proxy *target;
6096
Willy Tarreaua496b602006-12-17 23:15:24 +01006097 if (exp->action != ACT_SETBE)
6098 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006099
Alex Williams96532db2009-11-01 21:27:13 -05006100 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006101 if (!target) {
6102 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6103 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006104 cfgerr++;
6105 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006106 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6107 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006108 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006109 } else {
6110 free((void *)exp->replace);
6111 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006112 /* we force the backend to be present on at least all of
6113 * the frontend's processes.
6114 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006115 if (target->bind_proc)
6116 target->bind_proc = curproxy->bind_proc ?
6117 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006118 }
6119 }
6120 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006121
6122 /* find the target proxy for 'use_backend' rules */
6123 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006124 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006125 struct logformat_node *node;
6126 char *pxname;
6127
6128 /* Try to parse the string as a log format expression. If the result
6129 * of the parsing is only one entry containing a simple string, then
6130 * it's a standard string corresponding to a static rule, thus the
6131 * parsing is cancelled and be.name is restored to be resolved.
6132 */
6133 pxname = rule->be.name;
6134 LIST_INIT(&rule->be.expr);
6135 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6136 curproxy->conf.args.file, curproxy->conf.args.line);
6137 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6138
6139 if (!LIST_ISEMPTY(&rule->be.expr)) {
6140 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6141 rule->dynamic = 1;
6142 free(pxname);
6143 continue;
6144 }
6145 /* simple string: free the expression and fall back to static rule */
6146 free(node->arg);
6147 free(node);
6148 }
6149
6150 rule->dynamic = 0;
6151 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006152
Alex Williams96532db2009-11-01 21:27:13 -05006153 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006154
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006155 if (!target) {
6156 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6157 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006158 cfgerr++;
6159 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006160 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6161 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006162 cfgerr++;
6163 } else {
6164 free((void *)rule->be.name);
6165 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006166 /* we force the backend to be present on at least all of
6167 * the frontend's processes.
6168 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006169 if (target->bind_proc)
6170 target->bind_proc = curproxy->bind_proc ?
6171 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006172 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006173 }
6174
6175 /* find the target proxy for 'use_backend' rules */
6176 list_for_each_entry(srule, &curproxy->server_rules, list) {
6177 struct server *target = findserver(curproxy, srule->srv.name);
6178
6179 if (!target) {
6180 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6181 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6182 cfgerr++;
6183 continue;
6184 }
6185 free((void *)srule->srv.name);
6186 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006187 }
6188
Emeric Brunb982a3d2010-01-04 15:45:53 +01006189 /* find the target table for 'stick' rules */
6190 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6191 struct proxy *target;
6192
Emeric Brun1d33b292010-01-04 15:47:17 +01006193 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6194 if (mrule->flags & STK_IS_STORE)
6195 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6196
Emeric Brunb982a3d2010-01-04 15:45:53 +01006197 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006198 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006199 else
6200 target = curproxy;
6201
6202 if (!target) {
6203 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6204 curproxy->id, mrule->table.name);
6205 cfgerr++;
6206 }
6207 else if (target->table.size == 0) {
6208 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6209 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6210 cfgerr++;
6211 }
Willy Tarreau12785782012-04-27 21:37:17 +02006212 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6213 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006214 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6215 cfgerr++;
6216 }
6217 else {
6218 free((void *)mrule->table.name);
6219 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006220 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006221 }
6222 }
6223
6224 /* find the target table for 'store response' rules */
6225 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6226 struct proxy *target;
6227
Emeric Brun1d33b292010-01-04 15:47:17 +01006228 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6229
Emeric Brunb982a3d2010-01-04 15:45:53 +01006230 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006231 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006232 else
6233 target = curproxy;
6234
6235 if (!target) {
6236 Alert("Proxy '%s': unable to find store table '%s'.\n",
6237 curproxy->id, mrule->table.name);
6238 cfgerr++;
6239 }
6240 else if (target->table.size == 0) {
6241 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6242 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6243 cfgerr++;
6244 }
Willy Tarreau12785782012-04-27 21:37:17 +02006245 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6246 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006247 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6248 cfgerr++;
6249 }
6250 else {
6251 free((void *)mrule->table.name);
6252 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006253 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006254 }
6255 }
6256
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006257 /* find the target table for 'tcp-request' layer 4 rules */
6258 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6259 struct proxy *target;
6260
Willy Tarreaub4c84932013-07-23 19:15:30 +02006261 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006262 continue;
6263
6264 if (trule->act_prm.trk_ctr.table.n)
6265 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6266 else
6267 target = curproxy;
6268
6269 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006270 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6271 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006272 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006273 cfgerr++;
6274 }
6275 else if (target->table.size == 0) {
6276 Alert("Proxy '%s': table '%s' used but not configured.\n",
6277 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6278 cfgerr++;
6279 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006280 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6281 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6282 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 +01006283 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006284 cfgerr++;
6285 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006286 else {
6287 free(trule->act_prm.trk_ctr.table.n);
6288 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006289 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006290 * to pass a list of counters to track and allocate them right here using
6291 * stktable_alloc_data_type().
6292 */
6293 }
6294 }
6295
Willy Tarreaud1f96522010-08-03 19:34:32 +02006296 /* find the target table for 'tcp-request' layer 6 rules */
6297 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6298 struct proxy *target;
6299
Willy Tarreaub4c84932013-07-23 19:15:30 +02006300 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006301 continue;
6302
6303 if (trule->act_prm.trk_ctr.table.n)
6304 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6305 else
6306 target = curproxy;
6307
6308 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006309 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6310 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006311 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006312 cfgerr++;
6313 }
6314 else if (target->table.size == 0) {
6315 Alert("Proxy '%s': table '%s' used but not configured.\n",
6316 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6317 cfgerr++;
6318 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006319 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6320 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6321 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 +01006322 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006323 cfgerr++;
6324 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006325 else {
6326 free(trule->act_prm.trk_ctr.table.n);
6327 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006328 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006329 * to pass a list of counters to track and allocate them right here using
6330 * stktable_alloc_data_type().
6331 */
6332 }
6333 }
6334
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006335 /* move any "block" rules at the beginning of the http-request rules */
6336 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6337 /* insert block_rules into http_req_rules at the beginning */
6338 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6339 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6340 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6341 curproxy->http_req_rules.n = curproxy->block_rules.n;
6342 LIST_INIT(&curproxy->block_rules);
6343 }
6344
Emeric Brun32da3c42010-09-23 18:39:19 +02006345 if (curproxy->table.peers.name) {
6346 struct peers *curpeers = peers;
6347
6348 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6349 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6350 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006351 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006352 break;
6353 }
6354 }
6355
6356 if (!curpeers) {
6357 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6358 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006359 free((void *)curproxy->table.peers.name);
6360 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006361 cfgerr++;
6362 }
6363 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006364 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6365 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006366 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006367 cfgerr++;
6368 }
6369 }
6370
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006371 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006372 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006373 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6374 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6375 "proxy", curproxy->id);
6376 cfgerr++;
6377 goto out_uri_auth_compat;
6378 }
6379
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006380 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006381 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006382 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006383 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006384
Willy Tarreau95fa4692010-02-01 13:05:50 +01006385 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6386 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006387
6388 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006389 uri_auth_compat_req[i++] = "realm";
6390 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6391 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006392
Willy Tarreau95fa4692010-02-01 13:05:50 +01006393 uri_auth_compat_req[i++] = "unless";
6394 uri_auth_compat_req[i++] = "{";
6395 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6396 uri_auth_compat_req[i++] = "}";
6397 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006398
Willy Tarreauff011f22011-01-06 17:51:27 +01006399 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6400 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006401 cfgerr++;
6402 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006403 }
6404
Willy Tarreauff011f22011-01-06 17:51:27 +01006405 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006406
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006407 if (curproxy->uri_auth->auth_realm) {
6408 free(curproxy->uri_auth->auth_realm);
6409 curproxy->uri_auth->auth_realm = NULL;
6410 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006411
6412 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006413 }
6414out_uri_auth_compat:
6415
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006416 /* compile the log format */
6417 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006418 if (curproxy->conf.logformat_string != default_http_log_format &&
6419 curproxy->conf.logformat_string != default_tcp_log_format &&
6420 curproxy->conf.logformat_string != clf_http_log_format)
6421 free(curproxy->conf.logformat_string);
6422 curproxy->conf.logformat_string = NULL;
6423 free(curproxy->conf.lfs_file);
6424 curproxy->conf.lfs_file = NULL;
6425 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006426 }
6427
Willy Tarreau62a61232013-04-12 18:13:46 +02006428 if (curproxy->conf.logformat_string) {
6429 curproxy->conf.args.ctx = ARGC_LOG;
6430 curproxy->conf.args.file = curproxy->conf.lfs_file;
6431 curproxy->conf.args.line = curproxy->conf.lfs_line;
6432 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006433 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006434 curproxy->conf.args.file = NULL;
6435 curproxy->conf.args.line = 0;
6436 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006437
Willy Tarreau62a61232013-04-12 18:13:46 +02006438 if (curproxy->conf.uniqueid_format_string) {
6439 curproxy->conf.args.ctx = ARGC_UIF;
6440 curproxy->conf.args.file = curproxy->conf.uif_file;
6441 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006442 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006443 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6444 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006445 curproxy->conf.args.file = NULL;
6446 curproxy->conf.args.line = 0;
6447 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006448
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006449 /* only now we can check if some args remain unresolved.
6450 * This must be done after the users and groups resolution.
6451 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006452 cfgerr += smp_resolve_args(curproxy);
6453 if (!cfgerr)
6454 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006455
Willy Tarreau2738a142006-07-08 17:28:09 +02006456 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006457 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006458 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006459 (!curproxy->timeout.connect ||
6460 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006461 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006462 " | While not properly invalid, you will certainly encounter various problems\n"
6463 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006464 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006465 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006466 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006467 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006468
Willy Tarreau1fa31262007-12-03 00:36:16 +01006469 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6470 * We must still support older configurations, so let's find out whether those
6471 * parameters have been set or must be copied from contimeouts.
6472 */
6473 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006474 if (!curproxy->timeout.tarpit ||
6475 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006476 /* tarpit timeout not set. We search in the following order:
6477 * default.tarpit, curr.connect, default.connect.
6478 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006479 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006480 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006481 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006482 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006483 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006484 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006485 }
6486 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006487 (!curproxy->timeout.queue ||
6488 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006489 /* queue timeout not set. We search in the following order:
6490 * default.queue, curr.connect, default.connect.
6491 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006492 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006493 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006494 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006495 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006496 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006497 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006498 }
6499 }
6500
Willy Tarreau1620ec32011-08-06 17:05:02 +02006501 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006502 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6503 curproxy->check_req = (char *)malloc(curproxy->check_len);
6504 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006505 }
6506
Willy Tarreau193b8c62012-11-22 00:17:38 +01006507 /* ensure that cookie capture length is not too large */
6508 if (curproxy->capture_len >= global.tune.cookie_len) {
6509 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6510 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6511 err_code |= ERR_WARN;
6512 curproxy->capture_len = global.tune.cookie_len - 1;
6513 }
6514
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006515 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006516 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006517 curproxy->req_cap_pool = create_pool("ptrcap",
6518 curproxy->nb_req_cap * sizeof(char *),
6519 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006520 }
6521
6522 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006523 curproxy->rsp_cap_pool = create_pool("ptrcap",
6524 curproxy->nb_rsp_cap * sizeof(char *),
6525 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006526 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006527
Willy Tarreaubaaee002006-06-26 02:48:02 +02006528 /* first, we will invert the servers list order */
6529 newsrv = NULL;
6530 while (curproxy->srv) {
6531 struct server *next;
6532
6533 next = curproxy->srv->next;
6534 curproxy->srv->next = newsrv;
6535 newsrv = curproxy->srv;
6536 if (!next)
6537 break;
6538 curproxy->srv = next;
6539 }
6540
Willy Tarreau17edc812014-01-03 12:14:34 +01006541 /* Check that no server name conflicts. This causes trouble in the stats.
6542 * We only emit a warning for the first conflict affecting each server,
6543 * in order to avoid combinatory explosion if all servers have the same
6544 * name. We do that only for servers which do not have an explicit ID,
6545 * because these IDs were made also for distinguishing them and we don't
6546 * want to annoy people who correctly manage them.
6547 */
6548 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6549 struct server *other_srv;
6550
6551 if (newsrv->puid)
6552 continue;
6553
6554 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6555 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6556 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6557 newsrv->conf.file, newsrv->conf.line,
6558 proxy_type_str(curproxy), curproxy->id,
6559 newsrv->id, other_srv->conf.line);
6560 break;
6561 }
6562 }
6563 }
6564
Willy Tarreaudd701652010-05-25 23:03:02 +02006565 /* assign automatic UIDs to servers which don't have one yet */
6566 next_id = 1;
6567 newsrv = curproxy->srv;
6568 while (newsrv != NULL) {
6569 if (!newsrv->puid) {
6570 /* server ID not set, use automatic numbering with first
6571 * spare entry starting with next_svid.
6572 */
6573 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6574 newsrv->conf.id.key = newsrv->puid = next_id;
6575 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6576 }
6577 next_id++;
6578 newsrv = newsrv->next;
6579 }
6580
Willy Tarreau20697042007-11-15 23:26:18 +01006581 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006582 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583
Willy Tarreau62c3be22012-01-20 13:12:32 +01006584 /*
6585 * If this server supports a maxconn parameter, it needs a dedicated
6586 * tasks to fill the emptied slots when a connection leaves.
6587 * Also, resolve deferred tracking dependency if needed.
6588 */
6589 newsrv = curproxy->srv;
6590 while (newsrv != NULL) {
6591 if (newsrv->minconn > newsrv->maxconn) {
6592 /* Only 'minconn' was specified, or it was higher than or equal
6593 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6594 * this will avoid further useless expensive computations.
6595 */
6596 newsrv->maxconn = newsrv->minconn;
6597 } else if (newsrv->maxconn && !newsrv->minconn) {
6598 /* minconn was not specified, so we set it to maxconn */
6599 newsrv->minconn = newsrv->maxconn;
6600 }
6601
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006602#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006603 if (newsrv->use_ssl || newsrv->check.use_ssl)
6604 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006605#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006606
Willy Tarreau2f075e92013-12-03 11:11:34 +01006607 /* set the check type on the server */
6608 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6609
Willy Tarreau62c3be22012-01-20 13:12:32 +01006610 if (newsrv->trackit) {
6611 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006612 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006613 char *pname, *sname;
6614
6615 pname = newsrv->trackit;
6616 sname = strrchr(pname, '/');
6617
6618 if (sname)
6619 *sname++ = '\0';
6620 else {
6621 sname = pname;
6622 pname = NULL;
6623 }
6624
6625 if (pname) {
6626 px = findproxy(pname, PR_CAP_BE);
6627 if (!px) {
6628 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6629 proxy_type_str(curproxy), curproxy->id,
6630 newsrv->id, pname);
6631 cfgerr++;
6632 goto next_srv;
6633 }
6634 } else
6635 px = curproxy;
6636
6637 srv = findserver(px, sname);
6638 if (!srv) {
6639 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6640 proxy_type_str(curproxy), curproxy->id,
6641 newsrv->id, sname);
6642 cfgerr++;
6643 goto next_srv;
6644 }
6645
Willy Tarreau32091232014-05-16 13:52:00 +02006646 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6647 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6648 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006649 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006650 "tracking as it does not have any check nor agent enabled.\n",
6651 proxy_type_str(curproxy), curproxy->id,
6652 newsrv->id, px->id, srv->id);
6653 cfgerr++;
6654 goto next_srv;
6655 }
6656
6657 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6658
6659 if (loop) {
6660 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6661 "belongs to a tracking chain looping back to %s/%s.\n",
6662 proxy_type_str(curproxy), curproxy->id,
6663 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006664 cfgerr++;
6665 goto next_srv;
6666 }
6667
6668 if (curproxy != px &&
6669 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6670 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6671 "tracking: disable-on-404 option inconsistency.\n",
6672 proxy_type_str(curproxy), curproxy->id,
6673 newsrv->id, px->id, srv->id);
6674 cfgerr++;
6675 goto next_srv;
6676 }
6677
6678 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006679 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006680 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006681 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006682 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006683 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006684 }
6685
6686 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006687 newsrv->tracknext = srv->trackers;
6688 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006689
6690 free(newsrv->trackit);
6691 newsrv->trackit = NULL;
6692 }
6693 next_srv:
6694 newsrv = newsrv->next;
6695 }
6696
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006697 /* We have to initialize the server lookup mechanism depending
6698 * on what LB algorithm was choosen.
6699 */
6700
6701 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6702 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6703 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006704 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6705 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6706 init_server_map(curproxy);
6707 } else {
6708 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6709 fwrr_init_server_groups(curproxy);
6710 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006711 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006712
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006713 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006714 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6715 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6716 fwlc_init_server_tree(curproxy);
6717 } else {
6718 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6719 fas_init_server_tree(curproxy);
6720 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006721 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006722
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006723 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006724 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6725 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6726 chash_init_server_tree(curproxy);
6727 } else {
6728 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6729 init_server_map(curproxy);
6730 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006731 break;
6732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006733
6734 if (curproxy->options & PR_O_LOGASAP)
6735 curproxy->to_log &= ~LW_BYTES;
6736
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006737 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006738 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006739 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6740 proxy_type_str(curproxy), curproxy->id);
6741 err_code |= ERR_WARN;
6742 }
6743
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006744 if (curproxy->mode != PR_MODE_HTTP) {
6745 int optnum;
6746
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006747 if (curproxy->uri_auth) {
6748 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6749 proxy_type_str(curproxy), curproxy->id);
6750 err_code |= ERR_WARN;
6751 curproxy->uri_auth = NULL;
6752 }
6753
Willy Tarreau87cf5142011-08-19 22:57:24 +02006754 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006755 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6756 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6757 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006758 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006759 }
6760
6761 if (curproxy->options & PR_O_ORGTO) {
6762 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6763 "originalto", proxy_type_str(curproxy), curproxy->id);
6764 err_code |= ERR_WARN;
6765 curproxy->options &= ~PR_O_ORGTO;
6766 }
6767
6768 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6769 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6770 (curproxy->cap & cfg_opts[optnum].cap) &&
6771 (curproxy->options & cfg_opts[optnum].val)) {
6772 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6773 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6774 err_code |= ERR_WARN;
6775 curproxy->options &= ~cfg_opts[optnum].val;
6776 }
6777 }
6778
6779 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6780 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6781 (curproxy->cap & cfg_opts2[optnum].cap) &&
6782 (curproxy->options2 & cfg_opts2[optnum].val)) {
6783 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6784 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6785 err_code |= ERR_WARN;
6786 curproxy->options2 &= ~cfg_opts2[optnum].val;
6787 }
6788 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006789
Pieter Baauwd551fb52013-05-08 22:49:23 +02006790#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006791 if (curproxy->conn_src.bind_hdr_occ) {
6792 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006793 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006794 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006795 err_code |= ERR_WARN;
6796 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006797#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006798 }
6799
Willy Tarreaubaaee002006-06-26 02:48:02 +02006800 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006801 * ensure that we're not cross-dressing a TCP server into HTTP.
6802 */
6803 newsrv = curproxy->srv;
6804 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006805 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006806 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6807 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006808 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006809 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006810
Willy Tarreau0cec3312011-10-31 13:49:26 +01006811 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6812 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6813 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6814 err_code |= ERR_WARN;
6815 }
6816
Willy Tarreauc93cd162014-05-13 15:54:22 +02006817 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006818 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6819 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6820 err_code |= ERR_WARN;
6821 }
6822
Pieter Baauwd551fb52013-05-08 22:49:23 +02006823#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006824 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6825 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006826 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 +01006827 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006828 err_code |= ERR_WARN;
6829 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006830#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006831 newsrv = newsrv->next;
6832 }
6833
Willy Tarreauc1a21672009-08-16 22:37:44 +02006834 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006835 if (!curproxy->accept)
6836 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006837
Willy Tarreauc1a21672009-08-16 22:37:44 +02006838 if (curproxy->tcp_req.inspect_delay ||
6839 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006840 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006841
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006842 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006843 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006844 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006845 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006846
6847 /* both TCP and HTTP must check switching rules */
6848 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6849 }
6850
6851 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006852 if (curproxy->tcp_req.inspect_delay ||
6853 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6854 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6855
Emeric Brun97679e72010-09-23 17:56:44 +02006856 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6857 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6858
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006859 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006860 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006861 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006862 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006863
6864 /* If the backend does requires RDP cookie persistence, we have to
6865 * enable the corresponding analyser.
6866 */
6867 if (curproxy->options2 & PR_O2_RDPC_PRST)
6868 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6869 }
6870
Emeric Brunc52962f2012-11-15 18:28:02 +01006871#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006872 /* Configure SSL for each bind line.
6873 * Note: if configuration fails at some point, the ->ctx member
6874 * remains NULL so that listeners can later detach.
6875 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006876 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006877 int alloc_ctx;
6878
Emeric Brunc52962f2012-11-15 18:28:02 +01006879 if (!bind_conf->is_ssl) {
6880 if (bind_conf->default_ctx) {
6881 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6882 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6883 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006884 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006885 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006886 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006887 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006888 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006889 cfgerr++;
6890 continue;
6891 }
6892
Emeric Brun8dc60392014-05-09 13:52:00 +02006893 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006894 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02006895 if (alloc_ctx == SHCTX_E_INIT_LOCK)
6896 Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
6897 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006898 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02006899 cfgerr++;
6900 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006901 }
6902
Emeric Brunfc0421f2012-09-07 17:30:07 +02006903 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006904 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006905 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006906#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006907
Willy Tarreaue6b98942007-10-29 01:09:36 +01006908 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006909 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006910 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006911 if (!listener->luid) {
6912 /* listener ID not set, use automatic numbering with first
6913 * spare entry starting with next_luid.
6914 */
6915 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6916 listener->conf.id.key = listener->luid = next_id;
6917 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006918 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006919 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006920
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006921 /* enable separate counters */
6922 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6923 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006924 if (!listener->name)
6925 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006926 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006927
Willy Tarreaue6b98942007-10-29 01:09:36 +01006928 if (curproxy->options & PR_O_TCP_NOLING)
6929 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006930 if (!listener->maxconn)
6931 listener->maxconn = curproxy->maxconn;
6932 if (!listener->backlog)
6933 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006934 if (!listener->maxaccept)
6935 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6936
6937 /* we want to have an optimal behaviour on single process mode to
6938 * maximize the work at once, but in multi-process we want to keep
6939 * some fairness between processes, so we target half of the max
6940 * number of events to be balanced over all the processes the proxy
6941 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6942 * used to disable the limit.
6943 */
6944 if (listener->maxaccept > 0) {
6945 if (nbproc > 1)
6946 listener->maxaccept = (listener->maxaccept + 1) / 2;
6947 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6948 }
6949
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006950 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006951 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006952 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006953 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006954
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006955 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6956 listener->options |= LI_O_TCP_RULES;
6957
Willy Tarreaude3041d2010-05-31 10:56:17 +02006958 if (curproxy->mon_mask.s_addr)
6959 listener->options |= LI_O_CHK_MONNET;
6960
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006961 /* smart accept mode is automatic in HTTP mode */
6962 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006963 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006964 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6965 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006966 }
6967
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006968 /* Release unused SSL configs */
6969 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6970 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006971 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006972#ifdef USE_OPENSSL
6973 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006974 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006975 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006976 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006977 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006978#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006979 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006980
Willy Tarreau102df612014-05-07 23:56:38 +02006981 if (nbproc > 1) {
6982 if (curproxy->uri_auth) {
6983 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6984 curproxy->id);
6985 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6986 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6987 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006988 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006989 }
Willy Tarreau102df612014-05-07 23:56:38 +02006990 if (curproxy->appsession_name) {
6991 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6992 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006993 }
Willy Tarreau102df612014-05-07 23:56:38 +02006994 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6995 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6996 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006997 }
6998 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006999
7000 /* create the task associated with the proxy */
7001 curproxy->task = task_new();
7002 if (curproxy->task) {
7003 curproxy->task->context = curproxy;
7004 curproxy->task->process = manage_proxy;
7005 /* no need to queue, it will be done automatically if some
7006 * listener gets limited.
7007 */
7008 curproxy->task->expire = TICK_ETERNITY;
7009 } else {
7010 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7011 curproxy->id);
7012 cfgerr++;
7013 }
7014
Willy Tarreaubaaee002006-06-26 02:48:02 +02007015 curproxy = curproxy->next;
7016 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007017
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007018 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02007019 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02007020 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7021 unsigned long mask;
7022
7023 mask = nbits(global.nbproc);
7024 if (global.stats_fe->bind_proc)
7025 mask &= global.stats_fe->bind_proc;
7026
7027 if (bind_conf->bind_proc)
7028 mask &= bind_conf->bind_proc;
7029
7030 /* stop here if more than one process is used */
7031 if (popcount(mask) > 1)
7032 break;
7033 }
7034 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7035 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007036 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007037 }
7038
7039 /* automatically compute fullconn if not set. We must not do it in the
7040 * loop above because cross-references are not yet fully resolved.
7041 */
7042 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7043 /* If <fullconn> is not set, let's set it to 10% of the sum of
7044 * the possible incoming frontend's maxconns.
7045 */
7046 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7047 struct proxy *fe;
7048 int total = 0;
7049
7050 /* sum up the number of maxconns of frontends which
7051 * reference this backend at least once or which are
7052 * the same one ('listen').
7053 */
7054 for (fe = proxy; fe; fe = fe->next) {
7055 struct switching_rule *rule;
7056 struct hdr_exp *exp;
7057 int found = 0;
7058
7059 if (!(fe->cap & PR_CAP_FE))
7060 continue;
7061
7062 if (fe == curproxy) /* we're on a "listen" instance */
7063 found = 1;
7064
7065 if (fe->defbe.be == curproxy) /* "default_backend" */
7066 found = 1;
7067
7068 /* check if a "use_backend" rule matches */
7069 if (!found) {
7070 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007071 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007072 found = 1;
7073 break;
7074 }
7075 }
7076 }
7077
7078 /* check if a "reqsetbe" rule matches */
7079 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7080 if (exp->action == ACT_SETBE &&
7081 (struct proxy *)exp->replace == curproxy) {
7082 found = 1;
7083 break;
7084 }
7085 }
7086
7087 /* now we've checked all possible ways to reference a backend
7088 * from a frontend.
7089 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007090 if (!found)
7091 continue;
7092 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007093 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007094 /* we have the sum of the maxconns in <total>. We only
7095 * keep 10% of that sum to set the default fullconn, with
7096 * a hard minimum of 1 (to avoid a divide by zero).
7097 */
7098 curproxy->fullconn = (total + 9) / 10;
7099 if (!curproxy->fullconn)
7100 curproxy->fullconn = 1;
7101 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007102 }
7103
Willy Tarreau056f5682010-06-06 15:51:11 +02007104 /* initialize stick-tables on backend capable proxies. This must not
7105 * be done earlier because the data size may be discovered while parsing
7106 * other proxies.
7107 */
Godbach9703e662013-12-11 21:11:41 +08007108 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007109 if (curproxy->state == PR_STSTOPPED)
7110 continue;
7111
Godbach9703e662013-12-11 21:11:41 +08007112 if (!stktable_init(&curproxy->table)) {
7113 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7114 cfgerr++;
7115 }
7116 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007117
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007118 /*
7119 * Recount currently required checks.
7120 */
7121
7122 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7123 int optnum;
7124
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007125 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7126 if (curproxy->options & cfg_opts[optnum].val)
7127 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007128
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007129 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7130 if (curproxy->options2 & cfg_opts2[optnum].val)
7131 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007132 }
7133
Willy Tarreau122541c2011-09-07 21:24:49 +02007134 if (peers) {
7135 struct peers *curpeers = peers, **last;
7136 struct peer *p, *pb;
7137
7138 /* Remove all peers sections which don't have a valid listener.
7139 * This can happen when a peers section is never referenced and
7140 * does not contain a local peer.
7141 */
7142 last = &peers;
7143 while (*last) {
7144 curpeers = *last;
7145 if (curpeers->peers_fe) {
7146 last = &curpeers->next;
7147 continue;
7148 }
7149
7150 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7151 curpeers->id, localpeer);
7152
7153 p = curpeers->remote;
7154 while (p) {
7155 pb = p->next;
7156 free(p->id);
7157 free(p);
7158 p = pb;
7159 }
7160
7161 /* Destroy and unlink this curpeers section.
7162 * Note: curpeers is backed up into *last.
7163 */
7164 free(curpeers->id);
7165 curpeers = curpeers->next;
7166 free(*last);
7167 *last = curpeers;
7168 }
7169 }
7170
Willy Tarreau34eb6712011-10-24 18:15:04 +02007171 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007172 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007173 MEM_F_SHARED);
7174
Willy Tarreaubb925012009-07-23 13:36:36 +02007175 if (cfgerr > 0)
7176 err_code |= ERR_ALERT | ERR_FATAL;
7177 out:
7178 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007179}
7180
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007181/*
7182 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7183 * parsing sessions.
7184 */
7185void cfg_register_keywords(struct cfg_kw_list *kwl)
7186{
7187 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7188}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007189
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007190/*
7191 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7192 */
7193void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7194{
7195 LIST_DEL(&kwl->list);
7196 LIST_INIT(&kwl->list);
7197}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007198
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007199/* this function register new section in the haproxy configuration file.
7200 * <section_name> is the name of this new section and <section_parser>
7201 * is the called parser. If two section declaration have the same name,
7202 * only the first declared is used.
7203 */
7204int cfg_register_section(char *section_name,
7205 int (*section_parser)(const char *, int, char **, int))
7206{
7207 struct cfg_section *cs;
7208
7209 cs = calloc(1, sizeof(*cs));
7210 if (!cs) {
7211 Alert("register section '%s': out of memory.\n", section_name);
7212 return 0;
7213 }
7214
7215 cs->section_name = section_name;
7216 cs->section_parser = section_parser;
7217
7218 LIST_ADDQ(&sections, &cs->list);
7219
7220 return 1;
7221}
7222
Willy Tarreaubaaee002006-06-26 02:48:02 +02007223/*
7224 * Local variables:
7225 * c-indent-level: 8
7226 * c-basic-offset: 8
7227 * End:
7228 */