blob: 0a32df482c4d964685ab980df0ffed3f206f3134 [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 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200636#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200637 else if (!strcmp(args[0], "tune.bufsize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.bufsize = atol(args[1]);
644 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
645 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100646 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100647 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200648 }
649 else if (!strcmp(args[0], "tune.maxrewrite")) {
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.maxrewrite = atol(args[1]);
656 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
657 global.tune.maxrewrite = global.tune.bufsize / 2;
658 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100659 else if (!strcmp(args[0], "tune.idletimer")) {
660 unsigned int idle;
661 const char *res;
662
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668
669 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
670 if (res) {
671 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
672 file, linenum, *res, args[0]);
673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
675 }
676
677 if (idle > 65535) {
678 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.idle_timer = idle;
683 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100684 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
685 if (global.tune.client_rcvbuf != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT;
688 goto out;
689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.client_rcvbuf = atol(args[1]);
696 }
697 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
698 if (global.tune.server_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.server_rcvbuf = atol(args[1]);
709 }
710 else if (!strcmp(args[0], "tune.sndbuf.client")) {
711 if (global.tune.client_sndbuf != 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.client_sndbuf = atol(args[1]);
722 }
723 else if (!strcmp(args[0], "tune.sndbuf.server")) {
724 if (global.tune.server_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.server_sndbuf = atol(args[1]);
735 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200736 else if (!strcmp(args[0], "tune.pipesize")) {
737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 global.tune.pipesize = atol(args[1]);
743 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100744 else if (!strcmp(args[0], "tune.http.cookielen")) {
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
749 }
750 global.tune.cookie_len = atol(args[1]) + 1;
751 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200752 else if (!strcmp(args[0], "tune.http.maxhdr")) {
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 global.tune.max_http_hdr = atol(args[1]);
759 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100760 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
761#ifdef USE_ZLIB
762 if (*args[1]) {
763 global.tune.zlibmemlevel = atoi(args[1]);
764 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
765 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
766 file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 } else {
771 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
772 file, linenum, args[0]);
773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
775 }
776#else
777 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780#endif
781 }
782 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
783#ifdef USE_ZLIB
784 if (*args[1]) {
785 global.tune.zlibwindowsize = atoi(args[1]);
786 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
787 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
788 file, linenum, args[0]);
789 err_code |= ERR_ALERT | ERR_FATAL;
790 goto out;
791 }
792 } else {
793 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
794 file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798#else
799 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802#endif
803 }
William Lallemandf3747832012-11-09 12:33:10 +0100804 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
805 if (*args[1]) {
806 global.tune.comp_maxlevel = atoi(args[1]);
807 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
808 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
809 file, linenum, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813 } else {
814 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
815 file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 else if (!strcmp(args[0], "uid")) {
821 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200822 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200823 err_code |= ERR_ALERT;
824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200825 }
826 if (*(args[1]) == 0) {
827 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200830 }
831 global.uid = atol(args[1]);
832 }
833 else if (!strcmp(args[0], "gid")) {
834 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200835 Alert("parsing [%s:%d] : group/gid 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.gid = atol(args[1]);
845 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200846 /* user/group name handling */
847 else if (!strcmp(args[0], "user")) {
848 struct passwd *ha_user;
849 if (global.uid != 0) {
850 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200851 err_code |= ERR_ALERT;
852 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200853 }
854 errno = 0;
855 ha_user = getpwnam(args[1]);
856 if (ha_user != NULL) {
857 global.uid = (int)ha_user->pw_uid;
858 }
859 else {
860 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 +0200861 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200862 }
863 }
864 else if (!strcmp(args[0], "group")) {
865 struct group *ha_group;
866 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200867 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
869 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200870 }
871 errno = 0;
872 ha_group = getgrnam(args[1]);
873 if (ha_group != NULL) {
874 global.gid = (int)ha_group->gr_gid;
875 }
876 else {
877 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 +0200878 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200879 }
880 }
881 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100889 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
890 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
891 file, linenum, args[0], LONGBITS, global.nbproc);
892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 }
896 else if (!strcmp(args[0], "maxconn")) {
897 if (global.maxconn != 0) {
898 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200899 err_code |= ERR_ALERT;
900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901 }
902 if (*(args[1]) == 0) {
903 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 }
907 global.maxconn = atol(args[1]);
908#ifdef SYSTEM_MAXCONN
909 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
910 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);
911 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 }
914#endif /* SYSTEM_MAXCONN */
915 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200916 else if (!strcmp(args[0], "maxsslconn")) {
917#ifdef USE_OPENSSL
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923 global.maxsslconn = atol(args[1]);
924#else
Emeric Brun0914df82012-10-02 18:45:42 +0200925 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200928#endif
929 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100930 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
931#ifdef USE_OPENSSL
932 if (*(args[1]) == 0) {
933 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 free(global.listen_default_ciphers);
938 global.listen_default_ciphers = strdup(args[1]);
939#else
940 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943#endif
944 }
945 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
946#ifdef USE_OPENSSL
947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 free(global.connect_default_ciphers);
953 global.connect_default_ciphers = strdup(args[1]);
954#else
955 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958#endif
959 }
Emeric Brun850efd52014-01-29 12:24:34 +0100960 else if (!strcmp(args[0], "ssl-server-verify")) {
961 if (*(args[1]) == 0) {
962 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 if (strcmp(args[1],"none") == 0)
967 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
968 else if (strcmp(args[1],"required") == 0)
969 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
970 else {
971 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974 }
975 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200976 else if (!strcmp(args[0], "maxconnrate")) {
977 if (global.cps_lim != 0) {
978 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT;
980 goto out;
981 }
982 if (*(args[1]) == 0) {
983 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987 global.cps_lim = atol(args[1]);
988 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200989 else if (!strcmp(args[0], "maxsessrate")) {
990 if (global.sps_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.sps_lim = atol(args[1]);
1001 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001002 else if (!strcmp(args[0], "maxsslrate")) {
1003 if (global.ssl_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.ssl_lim = atol(args[1]);
1014 }
William Lallemandd85f9172012-11-09 17:05:39 +01001015 else if (!strcmp(args[0], "maxcomprate")) {
1016 if (*(args[1]) == 0) {
1017 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.comp_rate_lim = atoi(args[1]) * 1024;
1022 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001023 else if (!strcmp(args[0], "maxpipes")) {
1024 if (global.maxpipes != 0) {
1025 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001026 err_code |= ERR_ALERT;
1027 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001028 }
1029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001033 }
1034 global.maxpipes = atol(args[1]);
1035 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001036 else if (!strcmp(args[0], "maxzlibmem")) {
1037 if (*(args[1]) == 0) {
1038 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
William Lallemande3a7d992012-11-20 11:25:20 +01001042 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001043 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001044 else if (!strcmp(args[0], "maxcompcpuusage")) {
1045 if (*(args[1]) == 0) {
1046 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001051 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001052 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1053 err_code |= ERR_ALERT | ERR_FATAL;
1054 goto out;
1055 }
1056}
1057
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 else if (!strcmp(args[0], "ulimit-n")) {
1059 if (global.rlimit_nofile != 0) {
1060 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 err_code |= ERR_ALERT;
1062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 }
1064 if (*(args[1]) == 0) {
1065 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 global.rlimit_nofile = atol(args[1]);
1070 }
1071 else if (!strcmp(args[0], "chroot")) {
1072 if (global.chroot != NULL) {
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 a directory as an 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.chroot = strdup(args[1]);
1083 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001084 else if (!strcmp(args[0], "description")) {
1085 int i, len=0;
1086 char *d;
1087
1088 if (!*args[1]) {
1089 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1090 file, linenum, args[0]);
1091 err_code |= ERR_ALERT | ERR_FATAL;
1092 goto out;
1093 }
1094
Willy Tarreau348acfe2014-04-14 15:00:39 +02001095 for (i = 1; *args[i]; i++)
1096 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097
1098 if (global.desc)
1099 free(global.desc);
1100
1101 global.desc = d = (char *)calloc(1, len);
1102
Willy Tarreau348acfe2014-04-14 15:00:39 +02001103 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1104 for (i = 2; *args[i]; i++)
1105 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001106 }
1107 else if (!strcmp(args[0], "node")) {
1108 int i;
1109 char c;
1110
1111 for (i=0; args[1][i]; i++) {
1112 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001113 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1114 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001115 break;
1116 }
1117
1118 if (!i || args[1][i]) {
1119 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1120 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1121 file, linenum, args[0]);
1122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
1124 }
1125
1126 if (global.node)
1127 free(global.node);
1128
1129 global.node = strdup(args[1]);
1130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 else if (!strcmp(args[0], "pidfile")) {
1132 if (global.pidfile != NULL) {
1133 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001134 err_code |= ERR_ALERT;
1135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
1137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 }
1142 global.pidfile = strdup(args[1]);
1143 }
Emeric Bruned760922010-10-22 17:59:25 +02001144 else if (!strcmp(args[0], "unix-bind")) {
1145 int cur_arg = 1;
1146 while (*(args[cur_arg])) {
1147 if (!strcmp(args[cur_arg], "prefix")) {
1148 if (global.unix_bind.prefix != NULL) {
1149 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1150 err_code |= ERR_ALERT;
1151 cur_arg += 2;
1152 continue;
1153 }
1154
1155 if (*(args[cur_arg+1]) == 0) {
1156 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
1159 }
1160 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1161 cur_arg += 2;
1162 continue;
1163 }
1164
1165 if (!strcmp(args[cur_arg], "mode")) {
1166
1167 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1168 cur_arg += 2;
1169 continue;
1170 }
1171
1172 if (!strcmp(args[cur_arg], "uid")) {
1173
1174 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1175 cur_arg += 2;
1176 continue;
1177 }
1178
1179 if (!strcmp(args[cur_arg], "gid")) {
1180
1181 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1182 cur_arg += 2;
1183 continue;
1184 }
1185
1186 if (!strcmp(args[cur_arg], "user")) {
1187 struct passwd *user;
1188
1189 user = getpwnam(args[cur_arg + 1]);
1190 if (!user) {
1191 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1192 file, linenum, args[0], args[cur_arg + 1 ]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
1196
1197 global.unix_bind.ux.uid = user->pw_uid;
1198 cur_arg += 2;
1199 continue;
1200 }
1201
1202 if (!strcmp(args[cur_arg], "group")) {
1203 struct group *group;
1204
1205 group = getgrnam(args[cur_arg + 1]);
1206 if (!group) {
1207 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1208 file, linenum, args[0], args[cur_arg + 1 ]);
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 goto out;
1211 }
1212
1213 global.unix_bind.ux.gid = group->gr_gid;
1214 cur_arg += 2;
1215 continue;
1216 }
1217
Willy Tarreaub48f9582011-09-05 01:17:06 +02001218 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001219 file, linenum, args[0]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223 }
William Lallemand0f99e342011-10-12 17:50:54 +02001224 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1225 /* delete previous herited or defined syslog servers */
1226 struct logsrv *back;
1227 struct logsrv *tmp;
1228
1229 if (*(args[1]) != 0) {
1230 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234
1235 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1236 LIST_DEL(&tmp->list);
1237 free(tmp);
1238 }
1239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001241 struct sockaddr_storage *sk;
1242 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001243 struct logsrv *logsrv;
1244
Willy Tarreaubaaee002006-06-26 02:48:02 +02001245 if (*(args[1]) == 0 || *(args[2]) == 0) {
1246 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 }
William Lallemand0f99e342011-10-12 17:50:54 +02001250
1251 logsrv = calloc(1, sizeof(struct logsrv));
1252
1253 logsrv->facility = get_log_facility(args[2]);
1254 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001257 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259
William Lallemand0f99e342011-10-12 17:50:54 +02001260 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001262 logsrv->level = get_log_level(args[3]);
1263 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001265 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001266 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268 }
1269
William Lallemand0f99e342011-10-12 17:50:54 +02001270 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001271 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001272 logsrv->minlvl = get_log_level(args[4]);
1273 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001274 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001275 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001276 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001277 }
1278 }
1279
Willy Tarreau902636f2013-03-10 19:44:48 +01001280 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001281 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001282 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001283 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001284 free(logsrv);
1285 goto out;
1286 }
1287 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001288
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001289 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001290 if (port1 != port2) {
1291 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1292 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001293 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001294 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001295 goto out;
1296 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001297
William Lallemand0f99e342011-10-12 17:50:54 +02001298 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001299 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001300 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302
William Lallemand0f99e342011-10-12 17:50:54 +02001303 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001304 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001305 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1306 char *name;
1307 int len;
1308
1309 if (global.log_send_hostname != NULL) {
1310 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT;
1312 goto out;
1313 }
1314
1315 if (*(args[1]))
1316 name = args[1];
1317 else
1318 name = hostname;
1319
1320 len = strlen(name);
1321
1322 /* We'll add a space after the name to respect the log format */
1323 free(global.log_send_hostname);
1324 global.log_send_hostname = malloc(len + 2);
1325 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1326 }
Kevinm48936af2010-12-22 16:08:21 +00001327 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1328 if (*(args[1]) == 0) {
1329 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333 free(global.log_tag);
1334 global.log_tag = strdup(args[1]);
1335 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001336 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1337 if (global.spread_checks != 0) {
1338 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001339 err_code |= ERR_ALERT;
1340 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001341 }
1342 if (*(args[1]) == 0) {
1343 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001346 }
1347 global.spread_checks = atol(args[1]);
1348 if (global.spread_checks < 0 || global.spread_checks > 50) {
1349 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001350 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001353 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1354 const char *err;
1355 unsigned int val;
1356
1357
1358 if (*(args[1]) == 0) {
1359 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto out;
1362 }
1363
1364 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1365 if (err) {
1366 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1367 err_code |= ERR_ALERT | ERR_FATAL;
1368 }
1369 global.max_spread_checks = val;
1370 if (global.max_spread_checks < 0) {
1371 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1372 err_code |= ERR_ALERT | ERR_FATAL;
1373 }
1374 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001375 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1376#ifdef USE_CPU_AFFINITY
1377 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001378 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001379 unsigned long cpus = 0;
1380
1381 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001382 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001383 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001384 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001385 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001386 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001387 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001388 proc = atol(args[1]);
1389 if (proc >= 1 && proc <= LONGBITS)
1390 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001391 }
1392
1393 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001394 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",
1395 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001396 err_code |= ERR_ALERT | ERR_FATAL;
1397 goto out;
1398 }
1399
1400 cur_arg = 2;
1401 while (*args[cur_arg]) {
1402 unsigned int low, high;
1403
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001404 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001405 char *dash = strchr(args[cur_arg], '-');
1406
1407 low = high = str2uic(args[cur_arg]);
1408 if (dash)
1409 high = str2uic(dash + 1);
1410
1411 if (high < low) {
1412 unsigned int swap = low;
1413 low = high;
1414 high = swap;
1415 }
1416
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001417 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001418 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001419 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001420 err_code |= ERR_ALERT | ERR_FATAL;
1421 goto out;
1422 }
1423
1424 while (low <= high)
1425 cpus |= 1UL << low++;
1426 }
1427 else {
1428 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1429 file, linenum, args[0], args[cur_arg]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433 cur_arg++;
1434 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001435 for (i = 0; i < LONGBITS; i++)
1436 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001437 global.cpu_map[i] = cpus;
1438#else
1439 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
1442#endif
1443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001445 struct cfg_kw_list *kwl;
1446 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001447 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001448
1449 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1450 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1451 if (kwl->kw[index].section != CFG_GLOBAL)
1452 continue;
1453 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001454 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001455 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001456 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001458 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001459 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001460 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001461 err_code |= ERR_WARN;
1462 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001463 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001464 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001465 }
1466 }
1467 }
1468
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001470 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001472
Willy Tarreau058e9072009-07-20 09:30:05 +02001473 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001474 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001475 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476}
1477
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001478void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001480 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 defproxy.mode = PR_MODE_TCP;
1482 defproxy.state = PR_STNEW;
1483 defproxy.maxconn = cfg_maxpconn;
1484 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001485
Simon Horman66183002013-02-23 10:16:43 +09001486 defproxy.defsrv.check.inter = DEF_CHKINTR;
1487 defproxy.defsrv.check.fastinter = 0;
1488 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001489 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1490 defproxy.defsrv.agent.fastinter = 0;
1491 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001492 defproxy.defsrv.check.rise = DEF_RISETIME;
1493 defproxy.defsrv.check.fall = DEF_FALLTIME;
1494 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1495 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001496 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001497 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001498 defproxy.defsrv.maxqueue = 0;
1499 defproxy.defsrv.minconn = 0;
1500 defproxy.defsrv.maxconn = 0;
1501 defproxy.defsrv.slowstart = 0;
1502 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1503 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1504 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505}
1506
Willy Tarreauade5ec42010-01-28 19:33:49 +01001507
Willy Tarreau63af98d2014-05-18 08:11:41 +02001508/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1509 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1510 * ERR_FATAL in case of error.
1511 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001512static int create_cond_regex_rule(const char *file, int line,
1513 struct proxy *px, int dir, int action, int flags,
1514 const char *cmd, const char *reg, const char *repl,
1515 const char **cond_start)
1516{
1517 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001518 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001519 const char *err;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001520 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001521 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001522
1523 if (px == &defproxy) {
1524 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001525 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001526 goto err;
1527 }
1528
1529 if (*reg == 0) {
1530 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001531 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001532 goto err;
1533 }
1534
1535 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001536 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001537
Willy Tarreau5321c422010-01-28 20:35:13 +01001538 if (cond_start &&
1539 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001540 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1541 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1542 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001543 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001544 goto err;
1545 }
1546 }
1547 else if (cond_start && **cond_start) {
1548 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1549 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001550 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001551 goto err;
1552 }
1553
Willy Tarreau63af98d2014-05-18 08:11:41 +02001554 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001555 (dir == SMP_OPT_DIR_REQ) ?
1556 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1557 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1558 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001559
Willy Tarreauade5ec42010-01-28 19:33:49 +01001560 preg = calloc(1, sizeof(regex_t));
1561 if (!preg) {
1562 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001563 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001564 goto err;
1565 }
1566
1567 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1568 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001569 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001570 goto err;
1571 }
1572
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001573 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001574 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001575 if (repl && err) {
1576 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1577 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001578 ret_code |= ERR_ALERT | ERR_FATAL;
1579 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001580 }
1581
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001582 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001583 ret_code |= ERR_WARN;
1584
1585 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001586
Willy Tarreau63af98d2014-05-18 08:11:41 +02001587 err_free:
1588 regfree(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001589 err:
1590 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001591 free(errmsg);
1592 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001593}
1594
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001596 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001597 * Returns the error code, 0 if OK, or any combination of :
1598 * - ERR_ABORT: must abort ASAP
1599 * - ERR_FATAL: we can continue parsing but not start the service
1600 * - ERR_WARN: a warning has been emitted
1601 * - ERR_ALERT: an alert has been emitted
1602 * Only the two first ones can stop processing, the two others are just
1603 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001605int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1606{
1607 static struct peers *curpeers = NULL;
1608 struct peer *newpeer = NULL;
1609 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001610 struct bind_conf *bind_conf;
1611 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001612 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001613 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001614
1615 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001616 if (!*args[1]) {
1617 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001618 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001619 goto out;
1620 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001621
1622 err = invalid_char(args[1]);
1623 if (err) {
1624 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1625 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001626 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001627 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001628 }
1629
1630 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1631 /*
1632 * If there are two proxies with the same name only following
1633 * combinations are allowed:
1634 */
1635 if (strcmp(curpeers->id, args[1]) == 0) {
1636 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1637 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1638 err_code |= ERR_WARN;
1639 }
1640 }
1641
1642 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1643 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1644 err_code |= ERR_ALERT | ERR_ABORT;
1645 goto out;
1646 }
1647
1648 curpeers->next = peers;
1649 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001650 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001651 curpeers->conf.line = linenum;
1652 curpeers->last_change = now.tv_sec;
1653 curpeers->id = strdup(args[1]);
1654 }
1655 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001656 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001657 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001658 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001659
1660 if (!*args[2]) {
1661 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1662 file, linenum, args[0]);
1663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
1665 }
1666
1667 err = invalid_char(args[1]);
1668 if (err) {
1669 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1670 file, linenum, *err, args[1]);
1671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
1673 }
1674
1675 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1676 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1677 err_code |= ERR_ALERT | ERR_ABORT;
1678 goto out;
1679 }
1680
1681 /* the peers are linked backwards first */
1682 curpeers->count++;
1683 newpeer->next = curpeers->remote;
1684 curpeers->remote = newpeer;
1685 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001686 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001687 newpeer->conf.line = linenum;
1688
1689 newpeer->last_change = now.tv_sec;
1690 newpeer->id = strdup(args[1]);
1691
Willy Tarreau902636f2013-03-10 19:44:48 +01001692 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001693 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001694 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001697 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001698
1699 proto = protocol_by_family(sk->ss_family);
1700 if (!proto || !proto->connect) {
1701 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1702 file, linenum, args[0], args[1]);
1703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
1705 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001706
1707 if (port1 != port2) {
1708 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1709 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
1712 }
1713
Willy Tarreau2aa38802013-02-20 19:20:59 +01001714 if (!port1) {
1715 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1716 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
1719 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001720
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001722 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001723 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001724 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001725
Emeric Brun32da3c42010-09-23 18:39:19 +02001726 if (strcmp(newpeer->id, localpeer) == 0) {
1727 /* Current is local peer, it define a frontend */
1728 newpeer->local = 1;
1729
1730 if (!curpeers->peers_fe) {
1731 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1732 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1733 err_code |= ERR_ALERT | ERR_ABORT;
1734 goto out;
1735 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001736
Willy Tarreau237250c2011-07-29 01:49:03 +02001737 init_new_proxy(curpeers->peers_fe);
1738 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001739
1740 curpeers->peers_fe->last_change = now.tv_sec;
1741 curpeers->peers_fe->id = strdup(args[1]);
1742 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001743 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001744 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1745 curpeers->peers_fe->timeout.connect = 5000;
1746 curpeers->peers_fe->accept = peer_accept;
1747 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001748 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1749 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001750
1751 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1752
Willy Tarreau902636f2013-03-10 19:44:48 +01001753 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1754 if (errmsg && *errmsg) {
1755 indent_msg(&errmsg, 2);
1756 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001757 }
1758 else
1759 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1760 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001761 err_code |= ERR_FATAL;
1762 goto out;
1763 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001764
1765 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001766 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001767 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1768 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1769 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1770 l->accept = session_accept;
1771 l->handler = process_session;
1772 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1773 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1774 global.maxsock += l->maxconn;
1775 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001776 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001777 else {
1778 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1779 file, linenum, args[0], args[1],
1780 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1781 err_code |= ERR_FATAL;
1782 goto out;
1783 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001784 }
1785 } /* neither "peer" nor "peers" */
1786 else if (*args[0] != 0) {
1787 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791
1792out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001793 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001794 return err_code;
1795}
1796
Willy Tarreau3842f002009-06-14 11:39:52 +02001797int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798{
1799 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001800 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001801 int rc;
1802 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001803 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001804 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001805 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001806 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001807 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808
Willy Tarreau977b8e42006-12-29 14:19:17 +01001809 if (!strcmp(args[0], "listen"))
1810 rc = PR_CAP_LISTEN;
1811 else if (!strcmp(args[0], "frontend"))
1812 rc = PR_CAP_FE | PR_CAP_RS;
1813 else if (!strcmp(args[0], "backend"))
1814 rc = PR_CAP_BE | PR_CAP_RS;
1815 else if (!strcmp(args[0], "ruleset"))
1816 rc = PR_CAP_RS;
1817 else
1818 rc = PR_CAP_NONE;
1819
1820 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001821 struct ebpt_node *node;
1822
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 if (!*args[1]) {
1824 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1825 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1826 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001827 err_code |= ERR_ALERT | ERR_ABORT;
1828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001830
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001831 err = invalid_char(args[1]);
1832 if (err) {
1833 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1834 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001835 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001836 }
1837
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001838 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1839 curproxy = container_of(node, struct proxy, conf.by_name);
1840
1841 if (strcmp(curproxy->id, args[1]) != 0)
1842 break;
1843
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001844 /*
1845 * If there are two proxies with the same name only following
1846 * combinations are allowed:
1847 *
1848 * listen backend frontend ruleset
1849 * listen - - - -
1850 * backend - - OK -
1851 * frontend - OK - -
1852 * ruleset - - - -
1853 */
1854
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001855 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1856 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001857 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1858 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1859 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001861 }
1862 }
1863
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1865 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_ALERT | ERR_ABORT;
1867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001869
Willy Tarreau97cb7802010-01-03 20:23:58 +01001870 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->next = proxy;
1872 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001873 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1874 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001875 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001876 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001877 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001878 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001879
1880 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001881 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001882 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001883
Willy Tarreau4348fad2012-09-20 16:48:07 +02001884 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1885
Willy Tarreau902636f2013-03-10 19:44:48 +01001886 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1887 if (errmsg && *errmsg) {
1888 indent_msg(&errmsg, 2);
1889 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001890 }
1891 else
1892 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1893 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001894 err_code |= ERR_FATAL;
1895 goto out;
1896 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001897
Willy Tarreau4348fad2012-09-20 16:48:07 +02001898 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001899 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 }
1902
1903 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001904 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001905 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001906
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001909 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001910 curproxy->no_options = defproxy.no_options;
1911 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001912 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001913 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001914 curproxy->except_net = defproxy.except_net;
1915 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001916 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001917 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001919 if (defproxy.fwdfor_hdr_len) {
1920 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1921 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1922 }
1923
Willy Tarreaub86db342009-11-30 11:50:16 +01001924 if (defproxy.orgto_hdr_len) {
1925 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1926 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1927 }
1928
Mark Lamourinec2247f02012-01-04 13:02:01 -05001929 if (defproxy.server_id_hdr_len) {
1930 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1931 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1932 }
1933
Willy Tarreau977b8e42006-12-29 14:19:17 +01001934 if (curproxy->cap & PR_CAP_FE) {
1935 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001936 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001937 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001938
1939 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001940 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1941 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942
1943 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945
Willy Tarreau977b8e42006-12-29 14:19:17 +01001946 if (curproxy->cap & PR_CAP_BE) {
1947 curproxy->fullconn = defproxy.fullconn;
1948 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001949 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001951 if (defproxy.check_req) {
1952 curproxy->check_req = calloc(1, defproxy.check_len);
1953 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1954 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001957 if (defproxy.expect_str) {
1958 curproxy->expect_str = strdup(defproxy.expect_str);
1959 if (defproxy.expect_regex) {
1960 /* note: this regex is known to be valid */
1961 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1962 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1963 }
1964 }
1965
Willy Tarreau67402132012-05-31 20:40:20 +02001966 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001967 if (defproxy.cookie_name)
1968 curproxy->cookie_name = strdup(defproxy.cookie_name);
1969 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001970 if (defproxy.cookie_domain)
1971 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001972
Willy Tarreau31936852010-10-06 16:59:56 +02001973 if (defproxy.cookie_maxidle)
1974 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1975
1976 if (defproxy.cookie_maxlife)
1977 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1978
Emeric Brun647caf12009-06-30 17:57:00 +02001979 if (defproxy.rdp_cookie_name)
1980 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1981 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1982
Willy Tarreau01732802007-11-01 22:48:15 +01001983 if (defproxy.url_param_name)
1984 curproxy->url_param_name = strdup(defproxy.url_param_name);
1985 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001986
Benoitaffb4812009-03-25 13:02:10 +01001987 if (defproxy.hh_name)
1988 curproxy->hh_name = strdup(defproxy.hh_name);
1989 curproxy->hh_len = defproxy.hh_len;
1990 curproxy->hh_match_domain = defproxy.hh_match_domain;
1991
Willy Tarreauef9a3602012-12-08 22:29:20 +01001992 if (defproxy.conn_src.iface_name)
1993 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1994 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001995 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001996#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001997 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001998#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002001 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 if (defproxy.capture_name)
2003 curproxy->capture_name = strdup(defproxy.capture_name);
2004 curproxy->capture_namelen = defproxy.capture_namelen;
2005 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007
Willy Tarreau977b8e42006-12-29 14:19:17 +01002008 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002009 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002010 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002011 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002012 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002013 curproxy->mon_net = defproxy.mon_net;
2014 curproxy->mon_mask = defproxy.mon_mask;
2015 if (defproxy.monitor_uri)
2016 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2017 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002018 if (defproxy.defbe.name)
2019 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002020
2021 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002022 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2023 if (curproxy->conf.logformat_string &&
2024 curproxy->conf.logformat_string != default_http_log_format &&
2025 curproxy->conf.logformat_string != default_tcp_log_format &&
2026 curproxy->conf.logformat_string != clf_http_log_format)
2027 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2028
2029 if (defproxy.conf.lfs_file) {
2030 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2031 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2032 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002033 }
2034
2035 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002036 curproxy->timeout.connect = defproxy.timeout.connect;
2037 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002038 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002039 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002040 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002041 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002042 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002043 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002044 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002045 }
2046
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002048 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002049
2050 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002051 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002052 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002053 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002054 LIST_INIT(&node->list);
2055 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2056 }
2057
Willy Tarreau62a61232013-04-12 18:13:46 +02002058 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2059 if (curproxy->conf.uniqueid_format_string)
2060 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2061
2062 if (defproxy.conf.uif_file) {
2063 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2064 curproxy->conf.uif_line = defproxy.conf.uif_line;
2065 }
William Lallemanda73203e2012-03-12 12:48:57 +01002066
2067 /* copy default header unique id */
2068 if (defproxy.header_unique_id)
2069 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2070
William Lallemand82fe75c2012-10-23 10:25:10 +02002071 /* default compression options */
2072 if (defproxy.comp != NULL) {
2073 curproxy->comp = calloc(1, sizeof(struct comp));
2074 curproxy->comp->algos = defproxy.comp->algos;
2075 curproxy->comp->types = defproxy.comp->types;
2076 }
2077
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002079 curproxy->conf.used_listener_id = EB_ROOT;
2080 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002081
Willy Tarreau93893792009-07-23 13:19:11 +02002082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 }
2084 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2085 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002086 /* FIXME-20070101: we should do this too at the end of the
2087 * config parsing to free all default values.
2088 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002089 free(defproxy.check_req);
2090 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002091 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002092 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002093 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002094 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002095 free(defproxy.capture_name);
2096 free(defproxy.monitor_uri);
2097 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002098 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002099 free(defproxy.fwdfor_hdr_name);
2100 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002101 free(defproxy.orgto_hdr_name);
2102 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002103 free(defproxy.server_id_hdr_name);
2104 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002105 free(defproxy.expect_str);
2106 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002107
Willy Tarreau62a61232013-04-12 18:13:46 +02002108 if (defproxy.conf.logformat_string != default_http_log_format &&
2109 defproxy.conf.logformat_string != default_tcp_log_format &&
2110 defproxy.conf.logformat_string != clf_http_log_format)
2111 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002112
Willy Tarreau62a61232013-04-12 18:13:46 +02002113 free(defproxy.conf.uniqueid_format_string);
2114 free(defproxy.conf.lfs_file);
2115 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002116
Willy Tarreaua534fea2008-08-03 12:19:50 +02002117 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002118 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002119
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 /* we cannot free uri_auth because it might already be used */
2121 init_default_instance();
2122 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002123 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2124 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 }
2128 else if (curproxy == NULL) {
2129 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002133
2134 /* update the current file and line being parsed */
2135 curproxy->conf.args.file = curproxy->conf.file;
2136 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137
2138 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002139 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2140 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2141 if (err_code & ERR_FATAL)
2142 goto out;
2143 }
2144 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002145 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002146 int cur_arg;
2147
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 if (curproxy == &defproxy) {
2149 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155
Willy Tarreau24709282013-03-10 21:32:12 +01002156 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002157 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002162
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002163 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002164
2165 /* use default settings for unix sockets */
2166 bind_conf->ux.uid = global.unix_bind.ux.uid;
2167 bind_conf->ux.gid = global.unix_bind.ux.gid;
2168 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002169
2170 /* NOTE: the following line might create several listeners if there
2171 * are comma-separated IPs or port ranges. So all further processing
2172 * will have to be applied to all listeners created after last_listen.
2173 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002174 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2175 if (errmsg && *errmsg) {
2176 indent_msg(&errmsg, 2);
2177 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002178 }
2179 else
2180 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2181 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
2184 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002185
Willy Tarreau4348fad2012-09-20 16:48:07 +02002186 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2187 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002188 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002189 }
2190
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002191 cur_arg = 2;
2192 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002193 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002194 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002195 char *err;
2196
Willy Tarreau26982662012-09-12 23:17:10 +02002197 kw = bind_find_kw(args[cur_arg]);
2198 if (kw) {
2199 char *err = NULL;
2200 int code;
2201
2202 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002203 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2204 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002205 cur_arg += 1 + kw->skip ;
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
2208 }
2209
Willy Tarreau4348fad2012-09-20 16:48:07 +02002210 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002211 err_code |= code;
2212
2213 if (code) {
2214 if (err && *err) {
2215 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002216 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002217 }
2218 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002219 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2220 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002221 if (code & ERR_FATAL) {
2222 free(err);
2223 cur_arg += 1 + kw->skip;
2224 goto out;
2225 }
2226 }
2227 free(err);
2228 cur_arg += 1 + kw->skip;
2229 continue;
2230 }
2231
Willy Tarreau8638f482012-09-18 18:01:17 +02002232 err = NULL;
2233 if (!bind_dumped) {
2234 bind_dump_kws(&err);
2235 indent_msg(&err, 4);
2236 bind_dumped = 1;
2237 }
2238
2239 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2240 file, linenum, args[0], args[1], args[cur_arg],
2241 err ? " Registered keywords :" : "", err ? err : "");
2242 free(err);
2243
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002246 }
Willy Tarreau93893792009-07-23 13:19:11 +02002247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 }
2249 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002250 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2252 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002256 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 /* flush useless bits */
2260 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002263 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002266
Willy Tarreau1c47f852006-07-09 08:22:27 +02002267 if (!*args[1]) {
2268 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2269 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002272 }
2273
Willy Tarreaua534fea2008-08-03 12:19:50 +02002274 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002275 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002276 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002277 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002278 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2279
Willy Tarreau93893792009-07-23 13:19:11 +02002280 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2283 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2284 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2285 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2286 else {
2287 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 }
2291 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002292 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002293 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002294
2295 if (curproxy == &defproxy) {
2296 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002300 }
2301
2302 if (!*args[1]) {
2303 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2304 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002307 }
2308
2309 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002310 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002311
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002312 if (curproxy->uuid <= 0) {
2313 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002314 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002317 }
2318
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002319 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2320 if (node) {
2321 struct proxy *target = container_of(node, struct proxy, conf.id);
2322 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2323 file, linenum, proxy_type_str(curproxy), curproxy->id,
2324 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
2327 }
2328 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002329 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002330 else if (!strcmp(args[0], "description")) {
2331 int i, len=0;
2332 char *d;
2333
Cyril Bonté99ed3272010-01-24 23:29:44 +01002334 if (curproxy == &defproxy) {
2335 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2336 file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002341 if (!*args[1]) {
2342 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2343 file, linenum, args[0]);
2344 return -1;
2345 }
2346
Willy Tarreau348acfe2014-04-14 15:00:39 +02002347 for (i = 1; *args[i]; i++)
2348 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002349
2350 d = (char *)calloc(1, len);
2351 curproxy->desc = d;
2352
Willy Tarreau348acfe2014-04-14 15:00:39 +02002353 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2354 for (i = 2; *args[i]; i++)
2355 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002356
2357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2359 curproxy->state = PR_STSTOPPED;
2360 }
2361 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2362 curproxy->state = PR_STNEW;
2363 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002364 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2365 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002366 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002367
2368 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002369 unsigned int low, high;
2370
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002371 if (strcmp(args[cur_arg], "all") == 0) {
2372 set = 0;
2373 break;
2374 }
2375 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002376 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002377 }
2378 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002379 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002380 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002381 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002382 char *dash = strchr(args[cur_arg], '-');
2383
2384 low = high = str2uic(args[cur_arg]);
2385 if (dash)
2386 high = str2uic(dash + 1);
2387
2388 if (high < low) {
2389 unsigned int swap = low;
2390 low = high;
2391 high = swap;
2392 }
2393
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002394 if (low < 1 || high > LONGBITS) {
2395 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2396 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002399 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002400 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002401 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002402 }
2403 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002404 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2405 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002408 }
2409 cur_arg++;
2410 }
2411 curproxy->bind_proc = set;
2412 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002413 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002414 if (curproxy == &defproxy) {
2415 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002418 }
2419
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002420 err = invalid_char(args[1]);
2421 if (err) {
2422 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2423 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002425 }
2426
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002427 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002428 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2429 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002432 }
2433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2435 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436
Willy Tarreau977b8e42006-12-29 14:19:17 +01002437 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002439
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 if (*(args[1]) == 0) {
2441 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2442 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002446
Willy Tarreau67402132012-05-31 20:40:20 +02002447 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002448 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002449 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002450 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 curproxy->cookie_name = strdup(args[1]);
2452 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002453
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 cur_arg = 2;
2455 while (*(args[cur_arg])) {
2456 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002457 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
2459 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002460 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
2462 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002463 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 }
2465 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002466 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
2468 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002469 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002471 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002472 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002475 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002477 else if (!strcmp(args[cur_arg], "httponly")) {
2478 curproxy->ck_opts |= PR_CK_HTTPONLY;
2479 }
2480 else if (!strcmp(args[cur_arg], "secure")) {
2481 curproxy->ck_opts |= PR_CK_SECURE;
2482 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002483 else if (!strcmp(args[cur_arg], "domain")) {
2484 if (!*args[cur_arg + 1]) {
2485 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2486 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002489 }
2490
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002491 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002492 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002493 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2494 " dots nor does not start with a dot."
2495 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002496 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002497 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002498 }
2499
2500 err = invalid_domainchar(args[cur_arg + 1]);
2501 if (err) {
2502 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2503 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002506 }
2507
Willy Tarreau68a897b2009-12-03 23:28:34 +01002508 if (!curproxy->cookie_domain) {
2509 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2510 } else {
2511 /* one domain was already specified, add another one by
2512 * building the string which will be returned along with
2513 * the cookie.
2514 */
2515 char *new_ptr;
2516 int new_len = strlen(curproxy->cookie_domain) +
2517 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2518 new_ptr = malloc(new_len);
2519 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2520 free(curproxy->cookie_domain);
2521 curproxy->cookie_domain = new_ptr;
2522 }
Willy Tarreau31936852010-10-06 16:59:56 +02002523 cur_arg++;
2524 }
2525 else if (!strcmp(args[cur_arg], "maxidle")) {
2526 unsigned int maxidle;
2527 const char *res;
2528
2529 if (!*args[cur_arg + 1]) {
2530 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2531 file, linenum, args[cur_arg]);
2532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
2534 }
2535
2536 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2537 if (res) {
2538 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2539 file, linenum, *res, args[cur_arg]);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
2542 }
2543 curproxy->cookie_maxidle = maxidle;
2544 cur_arg++;
2545 }
2546 else if (!strcmp(args[cur_arg], "maxlife")) {
2547 unsigned int maxlife;
2548 const char *res;
2549
2550 if (!*args[cur_arg + 1]) {
2551 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2552 file, linenum, args[cur_arg]);
2553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
2555 }
2556
2557 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2558 if (res) {
2559 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2560 file, linenum, *res, args[cur_arg]);
2561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
2563 }
2564 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002565 cur_arg++;
2566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002568 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 +02002569 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
2573 cur_arg++;
2574 }
Willy Tarreau67402132012-05-31 20:40:20 +02002575 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2577 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
2580
Willy Tarreau67402132012-05-31 20:40:20 +02002581 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2583 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002586
Willy Tarreau67402132012-05-31 20:40:20 +02002587 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002588 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2589 file, linenum);
2590 err_code |= ERR_ALERT | ERR_FATAL;
2591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002593 else if (!strcmp(args[0], "persist")) { /* persist */
2594 if (*(args[1]) == 0) {
2595 Alert("parsing [%s:%d] : missing persist method.\n",
2596 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002599 }
2600
2601 if (!strncmp(args[1], "rdp-cookie", 10)) {
2602 curproxy->options2 |= PR_O2_RDPC_PRST;
2603
Emeric Brunb982a3d2010-01-04 15:45:53 +01002604 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002605 const char *beg, *end;
2606
2607 beg = args[1] + 11;
2608 end = strchr(beg, ')');
2609
2610 if (!end || end == beg) {
2611 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2612 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002615 }
2616
2617 free(curproxy->rdp_cookie_name);
2618 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2619 curproxy->rdp_cookie_len = end-beg;
2620 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002621 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002622 free(curproxy->rdp_cookie_name);
2623 curproxy->rdp_cookie_name = strdup("msts");
2624 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2625 }
2626 else { /* syntax */
2627 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2628 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002631 }
2632 }
2633 else {
2634 Alert("parsing [%s:%d] : unknown persist method.\n",
2635 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002638 }
2639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002641 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002643 if (curproxy == &defproxy) {
2644 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002653 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 }
2658 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002659 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 curproxy->appsession_name = strdup(args[1]);
2661 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2662 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002663 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2664 if (err) {
2665 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2666 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002669 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002670 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002671
Willy Tarreau51041c72007-09-09 21:56:53 +02002672 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2673 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_ABORT;
2675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002677
2678 cur_arg = 6;
2679 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002680 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2681 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002682 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002683 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002684 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002685 } else if (!strcmp(args[cur_arg], "prefix")) {
2686 curproxy->options2 |= PR_O2_AS_PFX;
2687 } else if (!strcmp(args[cur_arg], "mode")) {
2688 if (!*args[cur_arg + 1]) {
2689 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2690 file, linenum, args[0], args[cur_arg]);
2691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
2693 }
2694
2695 cur_arg++;
2696 if (!strcmp(args[cur_arg], "query-string")) {
2697 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2698 curproxy->options2 |= PR_O2_AS_M_QS;
2699 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2700 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2701 curproxy->options2 |= PR_O2_AS_M_PP;
2702 } else {
2703 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002708 cur_arg++;
2709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 } /* Url App Session */
2711 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002712 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002716 if (curproxy == &defproxy) {
2717 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
2720 }
2721
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 if (*(args[4]) == 0) {
2723 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2724 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002728 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 curproxy->capture_name = strdup(args[2]);
2730 curproxy->capture_namelen = strlen(curproxy->capture_name);
2731 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 curproxy->to_log |= LW_COOKIE;
2733 }
2734 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2735 struct cap_hdr *hdr;
2736
2737 if (curproxy == &defproxy) {
2738 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 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741 }
2742
2743 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2744 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2745 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 }
2749
2750 hdr = calloc(sizeof(struct cap_hdr), 1);
2751 hdr->next = curproxy->req_cap;
2752 hdr->name = strdup(args[3]);
2753 hdr->namelen = strlen(args[3]);
2754 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002755 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 hdr->index = curproxy->nb_req_cap++;
2757 curproxy->req_cap = hdr;
2758 curproxy->to_log |= LW_REQHDR;
2759 }
2760 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2761 struct cap_hdr *hdr;
2762
2763 if (curproxy == &defproxy) {
2764 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 +02002765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 }
2768
2769 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2770 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2771 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 }
2775 hdr = calloc(sizeof(struct cap_hdr), 1);
2776 hdr->next = curproxy->rsp_cap;
2777 hdr->name = strdup(args[3]);
2778 hdr->namelen = strlen(args[3]);
2779 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002780 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 hdr->index = curproxy->nb_rsp_cap++;
2782 curproxy->rsp_cap = hdr;
2783 curproxy->to_log |= LW_RSPHDR;
2784 }
2785 else {
2786 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2787 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 }
2791 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 if (*(args[1]) == 0) {
2797 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2798 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 }
2802 curproxy->conn_retries = atol(args[1]);
2803 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002804 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002805 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002806
2807 if (curproxy == &defproxy) {
2808 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
2812
Willy Tarreau20b0de52012-12-24 15:45:22 +01002813 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2814 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2815 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2816 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002817 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002818 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2819 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 +01002820 file, linenum, args[0]);
2821 err_code |= ERR_WARN;
2822 }
2823
Willy Tarreauff011f22011-01-06 17:51:27 +01002824 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002825
Willy Tarreauff011f22011-01-06 17:51:27 +01002826 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002827 err_code |= ERR_ALERT | ERR_ABORT;
2828 goto out;
2829 }
2830
Willy Tarreau5002f572014-04-23 01:32:02 +02002831 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002832 err_code |= warnif_cond_conflicts(rule->cond,
2833 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2834 file, linenum);
2835
Willy Tarreauff011f22011-01-06 17:51:27 +01002836 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002837 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002838 else if (!strcmp(args[0], "http-response")) { /* response access control */
2839 struct http_res_rule *rule;
2840
2841 if (curproxy == &defproxy) {
2842 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845 }
2846
2847 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2848 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2849 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2850 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2851 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2852 file, linenum, args[0]);
2853 err_code |= ERR_WARN;
2854 }
2855
2856 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2857
2858 if (!rule) {
2859 err_code |= ERR_ALERT | ERR_ABORT;
2860 goto out;
2861 }
2862
2863 err_code |= warnif_cond_conflicts(rule->cond,
2864 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2865 file, linenum);
2866
2867 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2868 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002869 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2870 /* set the header name and length into the proxy structure */
2871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2872 err_code |= ERR_WARN;
2873
2874 if (!*args[1]) {
2875 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2876 file, linenum, args[0]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880
2881 /* set the desired header name */
2882 free(curproxy->server_id_hdr_name);
2883 curproxy->server_id_hdr_name = strdup(args[1]);
2884 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2885 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002886 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002887 struct http_req_rule *rule;
2888
Willy Tarreaub099aca2008-10-12 17:26:37 +02002889 if (curproxy == &defproxy) {
2890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002893 }
2894
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002895 /* emulate "block" using "http-request block". Since these rules are supposed to
2896 * be processed before all http-request rules, we put them into their own list
2897 * and will insert them at the end.
2898 */
2899 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2900 if (!rule) {
2901 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002902 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002903 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002904 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2905 err_code |= warnif_cond_conflicts(rule->cond,
2906 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2907 file, linenum);
2908 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002909
2910 if (!already_warned(WARN_BLOCK_DEPRECATED))
2911 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]);
2912
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002913 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002914 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002915 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002916
Cyril Bonté99ed3272010-01-24 23:29:44 +01002917 if (curproxy == &defproxy) {
2918 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921 }
2922
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002923 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002924 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2925 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002928 }
2929
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002930 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002931 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002932 err_code |= warnif_cond_conflicts(rule->cond,
2933 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2934 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002935 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002936 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002937 struct switching_rule *rule;
2938
Willy Tarreaub099aca2008-10-12 17:26:37 +02002939 if (curproxy == &defproxy) {
2940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002943 }
2944
Willy Tarreau55ea7572007-06-17 19:56:27 +02002945 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002947
2948 if (*(args[1]) == 0) {
2949 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002952 }
2953
Willy Tarreauf51658d2014-04-23 01:21:56 +02002954 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2955 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2956 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2957 file, linenum, errmsg);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002961
Willy Tarreauf51658d2014-04-23 01:21:56 +02002962 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002963 }
2964
2965 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2966 rule->cond = cond;
2967 rule->be.name = strdup(args[1]);
2968 LIST_INIT(&rule->list);
2969 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2970 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002971 else if (strcmp(args[0], "use-server") == 0) {
2972 struct server_rule *rule;
2973
2974 if (curproxy == &defproxy) {
2975 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979
2980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2981 err_code |= ERR_WARN;
2982
2983 if (*(args[1]) == 0) {
2984 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
2989 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2990 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2991 file, linenum, args[0]);
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002996 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2997 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2998 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003003 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003004
3005 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3006 rule->cond = cond;
3007 rule->srv.name = strdup(args[1]);
3008 LIST_INIT(&rule->list);
3009 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3010 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3011 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003012 else if ((!strcmp(args[0], "force-persist")) ||
3013 (!strcmp(args[0], "ignore-persist"))) {
3014 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003015
3016 if (curproxy == &defproxy) {
3017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021
3022 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3023 err_code |= ERR_WARN;
3024
Willy Tarreauef6494c2010-01-28 17:12:36 +01003025 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003026 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3027 file, linenum, args[0]);
3028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
3030 }
3031
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003032 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3033 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3034 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
3037 }
3038
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003039 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3040 * where force-persist is applied.
3041 */
3042 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003043
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003044 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003045 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003046 if (!strcmp(args[0], "force-persist")) {
3047 rule->type = PERSIST_TYPE_FORCE;
3048 } else {
3049 rule->type = PERSIST_TYPE_IGNORE;
3050 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003051 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003052 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003053 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003054 else if (!strcmp(args[0], "stick-table")) {
3055 int myidx = 1;
3056
Emeric Brun32da3c42010-09-23 18:39:19 +02003057 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003058 curproxy->table.type = (unsigned int)-1;
3059 while (*args[myidx]) {
3060 const char *err;
3061
3062 if (strcmp(args[myidx], "size") == 0) {
3063 myidx++;
3064 if (!*(args[myidx])) {
3065 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3066 file, linenum, args[myidx-1]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
3070 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3071 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3072 file, linenum, *err, args[myidx-1]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
3075 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003076 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003077 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003078 else if (strcmp(args[myidx], "peers") == 0) {
3079 myidx++;
Godbach50523162013-12-11 19:48:57 +08003080 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003081 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3082 file, linenum, args[myidx-1]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Godbach50523162013-12-11 19:48:57 +08003085 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003086 curproxy->table.peers.name = strdup(args[myidx++]);
3087 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003088 else if (strcmp(args[myidx], "expire") == 0) {
3089 myidx++;
3090 if (!*(args[myidx])) {
3091 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3092 file, linenum, args[myidx-1]);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3097 if (err) {
3098 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3099 file, linenum, *err, args[myidx-1]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003104 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003105 }
3106 else if (strcmp(args[myidx], "nopurge") == 0) {
3107 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003108 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003109 }
3110 else if (strcmp(args[myidx], "type") == 0) {
3111 myidx++;
3112 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3113 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3114 file, linenum, args[myidx]);
3115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
3117 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003118 /* myidx already points to next arg */
3119 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003120 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003121 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003122 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003123
3124 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003125 nw = args[myidx];
3126 while (*nw) {
3127 /* the "store" keyword supports a comma-separated list */
3128 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003129 sa = NULL; /* store arg */
3130 while (*nw && *nw != ',') {
3131 if (*nw == '(') {
3132 *nw = 0;
3133 sa = ++nw;
3134 while (*nw != ')') {
3135 if (!*nw) {
3136 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3137 file, linenum, args[0], cw);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
3140 }
3141 nw++;
3142 }
3143 *nw = '\0';
3144 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003145 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003146 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003147 if (*nw)
3148 *nw++ = '\0';
3149 type = stktable_get_data_type(cw);
3150 if (type < 0) {
3151 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3152 file, linenum, args[0], cw);
3153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
3155 }
Willy Tarreauac782882010-06-20 10:41:54 +02003156
3157 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3158 switch (err) {
3159 case PE_NONE: break;
3160 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003161 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3162 file, linenum, args[0], cw);
3163 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003164 break;
3165
3166 case PE_ARG_MISSING:
3167 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3168 file, linenum, args[0], cw);
3169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
3171
3172 case PE_ARG_NOT_USED:
3173 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3174 file, linenum, args[0], cw);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177
3178 default:
3179 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3180 file, linenum, args[0], cw);
3181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003183 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003184 }
3185 myidx++;
3186 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003187 else {
3188 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3189 file, linenum, args[myidx]);
3190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003192 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003193 }
3194
3195 if (!curproxy->table.size) {
3196 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3197 file, linenum);
3198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
3200 }
3201
3202 if (curproxy->table.type == (unsigned int)-1) {
3203 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3204 file, linenum);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
3207 }
3208 }
3209 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003210 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003211 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003212 int myidx = 0;
3213 const char *name = NULL;
3214 int flags;
3215
3216 if (curproxy == &defproxy) {
3217 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
3221
3222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3223 err_code |= ERR_WARN;
3224 goto out;
3225 }
3226
3227 myidx++;
3228 if ((strcmp(args[myidx], "store") == 0) ||
3229 (strcmp(args[myidx], "store-request") == 0)) {
3230 myidx++;
3231 flags = STK_IS_STORE;
3232 }
3233 else if (strcmp(args[myidx], "store-response") == 0) {
3234 myidx++;
3235 flags = STK_IS_STORE | STK_ON_RSP;
3236 }
3237 else if (strcmp(args[myidx], "match") == 0) {
3238 myidx++;
3239 flags = STK_IS_MATCH;
3240 }
3241 else if (strcmp(args[myidx], "on") == 0) {
3242 myidx++;
3243 flags = STK_IS_MATCH | STK_IS_STORE;
3244 }
3245 else {
3246 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250
3251 if (*(args[myidx]) == 0) {
3252 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
3255 }
3256
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003257 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003258 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003259 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003260 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
3263 }
3264
3265 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003266 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3267 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3268 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003269 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003270 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003271 goto out;
3272 }
3273 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003274 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3275 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3276 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003277 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003278 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003279 goto out;
3280 }
3281 }
3282
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003283 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003284 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003285
Emeric Brunb982a3d2010-01-04 15:45:53 +01003286 if (strcmp(args[myidx], "table") == 0) {
3287 myidx++;
3288 name = args[myidx++];
3289 }
3290
Willy Tarreauef6494c2010-01-28 17:12:36 +01003291 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003292 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3293 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3294 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003295 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003296 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003297 goto out;
3298 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003299 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003300 else if (*(args[myidx])) {
3301 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3302 file, linenum, args[0], args[myidx]);
3303 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003304 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003305 goto out;
3306 }
Emeric Brun97679e72010-09-23 17:56:44 +02003307 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003308 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003309 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003310 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003311
Emeric Brunb982a3d2010-01-04 15:45:53 +01003312 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3313 rule->cond = cond;
3314 rule->expr = expr;
3315 rule->flags = flags;
3316 rule->table.name = name ? strdup(name) : NULL;
3317 LIST_INIT(&rule->list);
3318 if (flags & STK_ON_RSP)
3319 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3320 else
3321 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 else if (!strcmp(args[0], "stats")) {
3324 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3325 curproxy->uri_auth = NULL; /* we must detach from the default config */
3326
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003327 if (!*args[1]) {
3328 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003329 } else if (!strcmp(args[1], "admin")) {
3330 struct stats_admin_rule *rule;
3331
3332 if (curproxy == &defproxy) {
3333 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
3336 }
3337
3338 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3339 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3340 err_code |= ERR_ALERT | ERR_ABORT;
3341 goto out;
3342 }
3343
3344 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3345 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3346 file, linenum, args[0], args[1]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003350 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3351 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3352 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003357 err_code |= warnif_cond_conflicts(cond,
3358 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3359 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003360
3361 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3362 rule->cond = cond;
3363 LIST_INIT(&rule->list);
3364 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 } else if (!strcmp(args[1], "uri")) {
3366 if (*(args[2]) == 0) {
3367 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3371 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_ABORT;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
3375 } else if (!strcmp(args[1], "realm")) {
3376 if (*(args[2]) == 0) {
3377 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003382 err_code |= ERR_ALERT | ERR_ABORT;
3383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003385 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003386 unsigned interval;
3387
3388 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3389 if (err) {
3390 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3391 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003394 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3395 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_ABORT;
3397 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003398 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003399 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003400 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003401
3402 if (curproxy == &defproxy) {
3403 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3404 err_code |= ERR_ALERT | ERR_FATAL;
3405 goto out;
3406 }
3407
3408 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3409 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3410 err_code |= ERR_ALERT | ERR_ABORT;
3411 goto out;
3412 }
3413
Willy Tarreauff011f22011-01-06 17:51:27 +01003414 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3415 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003416 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3417 file, linenum, args[0]);
3418 err_code |= ERR_WARN;
3419 }
3420
Willy Tarreauff011f22011-01-06 17:51:27 +01003421 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003422
Willy Tarreauff011f22011-01-06 17:51:27 +01003423 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003424 err_code |= ERR_ALERT | ERR_ABORT;
3425 goto out;
3426 }
3427
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003428 err_code |= warnif_cond_conflicts(rule->cond,
3429 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3430 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003431 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003432
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 } else if (!strcmp(args[1], "auth")) {
3434 if (*(args[2]) == 0) {
3435 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3439 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_ABORT;
3441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
3443 } else if (!strcmp(args[1], "scope")) {
3444 if (*(args[2]) == 0) {
3445 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3449 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_ALERT | ERR_ABORT;
3451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 }
3453 } else if (!strcmp(args[1], "enable")) {
3454 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3455 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003456 err_code |= ERR_ALERT | ERR_ABORT;
3457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003459 } else if (!strcmp(args[1], "hide-version")) {
3460 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3461 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003462 err_code |= ERR_ALERT | ERR_ABORT;
3463 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003464 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003465 } else if (!strcmp(args[1], "show-legends")) {
3466 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3467 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3468 err_code |= ERR_ALERT | ERR_ABORT;
3469 goto out;
3470 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003471 } else if (!strcmp(args[1], "show-node")) {
3472
3473 if (*args[2]) {
3474 int i;
3475 char c;
3476
3477 for (i=0; args[2][i]; i++) {
3478 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003479 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3480 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003481 break;
3482 }
3483
3484 if (!i || args[2][i]) {
3485 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3486 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3487 file, linenum, args[0], args[1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491 }
3492
3493 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3494 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3495 err_code |= ERR_ALERT | ERR_ABORT;
3496 goto out;
3497 }
3498 } else if (!strcmp(args[1], "show-desc")) {
3499 char *desc = NULL;
3500
3501 if (*args[2]) {
3502 int i, len=0;
3503 char *d;
3504
Willy Tarreau348acfe2014-04-14 15:00:39 +02003505 for (i = 2; *args[i]; i++)
3506 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003507
3508 desc = d = (char *)calloc(1, len);
3509
Willy Tarreau348acfe2014-04-14 15:00:39 +02003510 d += snprintf(d, desc + len - d, "%s", args[2]);
3511 for (i = 3; *args[i]; i++)
3512 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003513 }
3514
3515 if (!*args[2] && !global.desc)
3516 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3517 file, linenum, args[1]);
3518 else {
3519 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3520 free(desc);
3521 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3522 err_code |= ERR_ALERT | ERR_ABORT;
3523 goto out;
3524 }
3525 free(desc);
3526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003528stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003529 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 +01003530 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 }
3534 }
3535 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003536 int optnum;
3537
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003538 if (*(args[1]) == '\0') {
3539 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3540 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003544
3545 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3546 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003547 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3548 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3549 file, linenum, cfg_opts[optnum].name);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
Willy Tarreau93893792009-07-23 13:19:11 +02003553 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3554 err_code |= ERR_WARN;
3555 goto out;
3556 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003557
Willy Tarreau3842f002009-06-14 11:39:52 +02003558 curproxy->no_options &= ~cfg_opts[optnum].val;
3559 curproxy->options &= ~cfg_opts[optnum].val;
3560
3561 switch (kwm) {
3562 case KWM_STD:
3563 curproxy->options |= cfg_opts[optnum].val;
3564 break;
3565 case KWM_NO:
3566 curproxy->no_options |= cfg_opts[optnum].val;
3567 break;
3568 case KWM_DEF: /* already cleared */
3569 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003570 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003571
Willy Tarreau93893792009-07-23 13:19:11 +02003572 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003573 }
3574 }
3575
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003576 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3577 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003578 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3579 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3580 file, linenum, cfg_opts2[optnum].name);
3581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
3583 }
Willy Tarreau93893792009-07-23 13:19:11 +02003584 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3585 err_code |= ERR_WARN;
3586 goto out;
3587 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003588
Willy Tarreau3842f002009-06-14 11:39:52 +02003589 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3590 curproxy->options2 &= ~cfg_opts2[optnum].val;
3591
3592 switch (kwm) {
3593 case KWM_STD:
3594 curproxy->options2 |= cfg_opts2[optnum].val;
3595 break;
3596 case KWM_NO:
3597 curproxy->no_options2 |= cfg_opts2[optnum].val;
3598 break;
3599 case KWM_DEF: /* already cleared */
3600 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003601 }
Willy Tarreau93893792009-07-23 13:19:11 +02003602 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003603 }
3604 }
3605
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003606 /* HTTP options override each other. They can be cancelled using
3607 * "no option xxx" which only switches to default mode if the mode
3608 * was this one (useful for cancelling options set in defaults
3609 * sections).
3610 */
3611 if (strcmp(args[1], "httpclose") == 0) {
3612 if (kwm == KWM_STD) {
3613 curproxy->options &= ~PR_O_HTTP_MODE;
3614 curproxy->options |= PR_O_HTTP_PCL;
3615 goto out;
3616 }
3617 else if (kwm == KWM_NO) {
3618 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3619 curproxy->options &= ~PR_O_HTTP_MODE;
3620 goto out;
3621 }
3622 }
3623 else if (strcmp(args[1], "forceclose") == 0) {
3624 if (kwm == KWM_STD) {
3625 curproxy->options &= ~PR_O_HTTP_MODE;
3626 curproxy->options |= PR_O_HTTP_FCL;
3627 goto out;
3628 }
3629 else if (kwm == KWM_NO) {
3630 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3631 curproxy->options &= ~PR_O_HTTP_MODE;
3632 goto out;
3633 }
3634 }
3635 else if (strcmp(args[1], "http-server-close") == 0) {
3636 if (kwm == KWM_STD) {
3637 curproxy->options &= ~PR_O_HTTP_MODE;
3638 curproxy->options |= PR_O_HTTP_SCL;
3639 goto out;
3640 }
3641 else if (kwm == KWM_NO) {
3642 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3643 curproxy->options &= ~PR_O_HTTP_MODE;
3644 goto out;
3645 }
3646 }
3647 else if (strcmp(args[1], "http-keep-alive") == 0) {
3648 if (kwm == KWM_STD) {
3649 curproxy->options &= ~PR_O_HTTP_MODE;
3650 curproxy->options |= PR_O_HTTP_KAL;
3651 goto out;
3652 }
3653 else if (kwm == KWM_NO) {
3654 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3655 curproxy->options &= ~PR_O_HTTP_MODE;
3656 goto out;
3657 }
3658 }
3659 else if (strcmp(args[1], "http-tunnel") == 0) {
3660 if (kwm == KWM_STD) {
3661 curproxy->options &= ~PR_O_HTTP_MODE;
3662 curproxy->options |= PR_O_HTTP_TUN;
3663 goto out;
3664 }
3665 else if (kwm == KWM_NO) {
3666 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3667 curproxy->options &= ~PR_O_HTTP_MODE;
3668 goto out;
3669 }
3670 }
3671
Willy Tarreau3842f002009-06-14 11:39:52 +02003672 if (kwm != KWM_STD) {
3673 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003674 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003677 }
3678
Emeric Brun3a058f32009-06-30 18:26:00 +02003679 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003680 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003681 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003682 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003683 if (*(args[2]) != '\0') {
3684 if (!strcmp(args[2], "clf")) {
3685 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003686 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003687 } else {
3688 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003691 }
3692 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003693 if (curproxy->conf.logformat_string != default_http_log_format &&
3694 curproxy->conf.logformat_string != default_tcp_log_format &&
3695 curproxy->conf.logformat_string != clf_http_log_format)
3696 free(curproxy->conf.logformat_string);
3697 curproxy->conf.logformat_string = logformat;
3698
3699 free(curproxy->conf.lfs_file);
3700 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3701 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003702 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003703 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003705 if (curproxy->conf.logformat_string != default_http_log_format &&
3706 curproxy->conf.logformat_string != default_tcp_log_format &&
3707 curproxy->conf.logformat_string != clf_http_log_format)
3708 free(curproxy->conf.logformat_string);
3709 curproxy->conf.logformat_string = default_tcp_log_format;
3710
3711 free(curproxy->conf.lfs_file);
3712 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3713 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 else if (!strcmp(args[1], "tcpka")) {
3716 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003717 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003719
3720 if (curproxy->cap & PR_CAP_FE)
3721 curproxy->options |= PR_O_TCP_CLI_KA;
3722 if (curproxy->cap & PR_CAP_BE)
3723 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 }
3725 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_WARN;
3728
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003730 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003731 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003732 curproxy->options2 &= ~PR_O2_CHK_ANY;
3733 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 if (!*args[2]) { /* no argument */
3735 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3736 curproxy->check_len = strlen(DEF_CHECK_REQ);
3737 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003738 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 curproxy->check_req = (char *)malloc(reqlen);
3740 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003741 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003743 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 if (*args[4])
3745 reqlen += strlen(args[4]);
3746 else
3747 reqlen += strlen("HTTP/1.0");
3748
3749 curproxy->check_req = (char *)malloc(reqlen);
3750 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003751 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003753 }
3754 else if (!strcmp(args[1], "ssl-hello-chk")) {
3755 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003758
Willy Tarreaua534fea2008-08-03 12:19:50 +02003759 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003760 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003761 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003762 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763 }
Willy Tarreau23677902007-05-08 23:50:35 +02003764 else if (!strcmp(args[1], "smtpchk")) {
3765 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003766 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003767 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003768 curproxy->options2 &= ~PR_O2_CHK_ANY;
3769 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003770
3771 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3772 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3773 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3774 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3775 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3776 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3777 curproxy->check_req = (char *)malloc(reqlen);
3778 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3779 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3780 } else {
3781 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3782 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3783 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3784 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3785 }
3786 }
3787 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003788 else if (!strcmp(args[1], "pgsql-check")) {
3789 /* use PostgreSQL request to check servers' health */
3790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3791 err_code |= ERR_WARN;
3792
3793 free(curproxy->check_req);
3794 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003795 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003796 curproxy->options2 |= PR_O2_PGSQL_CHK;
3797
3798 if (*(args[2])) {
3799 int cur_arg = 2;
3800
3801 while (*(args[cur_arg])) {
3802 if (strcmp(args[cur_arg], "user") == 0) {
3803 char * packet;
3804 uint32_t packet_len;
3805 uint32_t pv;
3806
3807 /* suboption header - needs additional argument for it */
3808 if (*(args[cur_arg+1]) == 0) {
3809 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3810 file, linenum, args[0], args[1], args[cur_arg]);
3811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
3813 }
3814
3815 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3816 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3817 pv = htonl(0x30000); /* protocol version 3.0 */
3818
3819 packet = (char*) calloc(1, packet_len);
3820
3821 memcpy(packet + 4, &pv, 4);
3822
3823 /* copy "user" */
3824 memcpy(packet + 8, "user", 4);
3825
3826 /* copy username */
3827 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3828
3829 free(curproxy->check_req);
3830 curproxy->check_req = packet;
3831 curproxy->check_len = packet_len;
3832
3833 packet_len = htonl(packet_len);
3834 memcpy(packet, &packet_len, 4);
3835 cur_arg += 2;
3836 } else {
3837 /* unknown suboption - catchall */
3838 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3839 file, linenum, args[0], args[1]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 } /* end while loop */
3844 }
3845 }
3846
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003847 else if (!strcmp(args[1], "redis-check")) {
3848 /* use REDIS PING request to check servers' health */
3849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3850 err_code |= ERR_WARN;
3851
3852 free(curproxy->check_req);
3853 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003854 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003855 curproxy->options2 |= PR_O2_REDIS_CHK;
3856
3857 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3858 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3859 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3860 }
3861
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003862 else if (!strcmp(args[1], "mysql-check")) {
3863 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3865 err_code |= ERR_WARN;
3866
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003867 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003868 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003869 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003870 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003871
3872 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3873 * const char mysql40_client_auth_pkt[] = {
3874 * "\x0e\x00\x00" // packet length
3875 * "\x01" // packet number
3876 * "\x00\x00" // client capabilities
3877 * "\x00\x00\x01" // max packet
3878 * "haproxy\x00" // username (null terminated string)
3879 * "\x00" // filler (always 0x00)
3880 * "\x01\x00\x00" // packet length
3881 * "\x00" // packet number
3882 * "\x01" // COM_QUIT command
3883 * };
3884 */
3885
3886 if (*(args[2])) {
3887 int cur_arg = 2;
3888
3889 while (*(args[cur_arg])) {
3890 if (strcmp(args[cur_arg], "user") == 0) {
3891 char *mysqluser;
3892 int packetlen, reqlen, userlen;
3893
3894 /* suboption header - needs additional argument for it */
3895 if (*(args[cur_arg+1]) == 0) {
3896 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3897 file, linenum, args[0], args[1], args[cur_arg]);
3898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
3900 }
3901 mysqluser = args[cur_arg + 1];
3902 userlen = strlen(mysqluser);
3903 packetlen = userlen + 7;
3904 reqlen = packetlen + 9;
3905
3906 free(curproxy->check_req);
3907 curproxy->check_req = (char *)calloc(1, reqlen);
3908 curproxy->check_len = reqlen;
3909
3910 snprintf(curproxy->check_req, 4, "%c%c%c",
3911 ((unsigned char) packetlen & 0xff),
3912 ((unsigned char) (packetlen >> 8) & 0xff),
3913 ((unsigned char) (packetlen >> 16) & 0xff));
3914
3915 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003916 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003917 curproxy->check_req[8] = 1;
3918 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3919 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3920 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3921 cur_arg += 2;
3922 } else {
3923 /* unknown suboption - catchall */
3924 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3925 file, linenum, args[0], args[1]);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929 } /* end while loop */
3930 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003931 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003932 else if (!strcmp(args[1], "ldap-check")) {
3933 /* use LDAP request to check servers' health */
3934 free(curproxy->check_req);
3935 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003936 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003937 curproxy->options2 |= PR_O2_LDAP_CHK;
3938
3939 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3940 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3941 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3942 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003943 else if (!strcmp(args[1], "tcp-check")) {
3944 /* use raw TCPCHK send/expect to check servers' health */
3945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3946 err_code |= ERR_WARN;
3947
3948 free(curproxy->check_req);
3949 curproxy->check_req = NULL;
3950 curproxy->options2 &= ~PR_O2_CHK_ANY;
3951 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3952 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003953 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003954 int cur_arg;
3955
3956 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3957 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003958 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003959
Willy Tarreau87cf5142011-08-19 22:57:24 +02003960 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003961
3962 free(curproxy->fwdfor_hdr_name);
3963 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3964 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3965
3966 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3967 cur_arg = 2;
3968 while (*(args[cur_arg])) {
3969 if (!strcmp(args[cur_arg], "except")) {
3970 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003971 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003972 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3973 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003976 }
3977 /* flush useless bits */
3978 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003979 cur_arg += 2;
3980 } else if (!strcmp(args[cur_arg], "header")) {
3981 /* suboption header - needs additional argument for it */
3982 if (*(args[cur_arg+1]) == 0) {
3983 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3984 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003987 }
3988 free(curproxy->fwdfor_hdr_name);
3989 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3990 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3991 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003992 } else if (!strcmp(args[cur_arg], "if-none")) {
3993 curproxy->options &= ~PR_O_FF_ALWAYS;
3994 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003995 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003996 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003997 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003998 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004001 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004002 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004003 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004004 else if (!strcmp(args[1], "originalto")) {
4005 int cur_arg;
4006
4007 /* insert x-original-to field, but not for the IP address listed as an except.
4008 * set default options (ie: bitfield, header name, etc)
4009 */
4010
4011 curproxy->options |= PR_O_ORGTO;
4012
4013 free(curproxy->orgto_hdr_name);
4014 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4015 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4016
Willy Tarreau87cf5142011-08-19 22:57:24 +02004017 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004018 cur_arg = 2;
4019 while (*(args[cur_arg])) {
4020 if (!strcmp(args[cur_arg], "except")) {
4021 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004022 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 +02004023 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4024 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004027 }
4028 /* flush useless bits */
4029 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4030 cur_arg += 2;
4031 } else if (!strcmp(args[cur_arg], "header")) {
4032 /* suboption header - needs additional argument for it */
4033 if (*(args[cur_arg+1]) == 0) {
4034 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> 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;
Maik Broemme2850cb42009-04-17 18:53:21 +02004038 }
4039 free(curproxy->orgto_hdr_name);
4040 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4041 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4042 cur_arg += 2;
4043 } else {
4044 /* unknown suboption - catchall */
4045 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4046 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004049 }
4050 } /* end while loop */
4051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 else {
4053 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 }
Willy Tarreau93893792009-07-23 13:19:11 +02004057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004059 else if (!strcmp(args[0], "default_backend")) {
4060 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004062
4063 if (*(args[1]) == 0) {
4064 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004067 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004068 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004069 curproxy->defbe.name = strdup(args[1]);
4070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004072 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004073 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004074
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004075 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4076 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 +01004077 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004079 /* enable reconnections to dispatch */
4080 curproxy->options |= PR_O_REDISP;
4081 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004082 else if (!strcmp(args[0], "http-check")) {
4083 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004085
4086 if (strcmp(args[1], "disable-on-404") == 0) {
4087 /* enable a graceful server shutdown on an HTTP 404 response */
4088 curproxy->options |= PR_O_DISABLE404;
4089 }
Willy Tarreauef781042010-01-27 11:53:01 +01004090 else if (strcmp(args[1], "send-state") == 0) {
4091 /* enable emission of the apparent state of a server in HTTP checks */
4092 curproxy->options2 |= PR_O2_CHK_SNDST;
4093 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004094 else if (strcmp(args[1], "expect") == 0) {
4095 const char *ptr_arg;
4096 int cur_arg;
4097
4098 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4099 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103
4104 cur_arg = 2;
4105 /* consider exclamation marks, sole or at the beginning of a word */
4106 while (*(ptr_arg = args[cur_arg])) {
4107 while (*ptr_arg == '!') {
4108 curproxy->options2 ^= PR_O2_EXP_INV;
4109 ptr_arg++;
4110 }
4111 if (*ptr_arg)
4112 break;
4113 cur_arg++;
4114 }
4115 /* now ptr_arg points to the beginning of a word past any possible
4116 * exclamation mark, and cur_arg is the argument which holds this word.
4117 */
4118 if (strcmp(ptr_arg, "status") == 0) {
4119 if (!*(args[cur_arg + 1])) {
4120 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4121 file, linenum, args[0], args[1], ptr_arg);
4122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
4124 }
4125 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004126 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004127 curproxy->expect_str = strdup(args[cur_arg + 1]);
4128 }
4129 else if (strcmp(ptr_arg, "string") == 0) {
4130 if (!*(args[cur_arg + 1])) {
4131 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4132 file, linenum, args[0], args[1], ptr_arg);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004137 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004138 curproxy->expect_str = strdup(args[cur_arg + 1]);
4139 }
4140 else if (strcmp(ptr_arg, "rstatus") == 0) {
4141 if (!*(args[cur_arg + 1])) {
4142 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4143 file, linenum, args[0], args[1], ptr_arg);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004148 free(curproxy->expect_str);
4149 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4150 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004151 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4152 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4153 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4154 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
4157 }
4158 }
4159 else if (strcmp(ptr_arg, "rstring") == 0) {
4160 if (!*(args[cur_arg + 1])) {
4161 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4162 file, linenum, args[0], args[1], ptr_arg);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
4166 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004167 free(curproxy->expect_str);
4168 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4169 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004170 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4171 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4172 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4173 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
4177 }
4178 else {
4179 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4180 file, linenum, args[0], args[1], ptr_arg);
4181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
4183 }
4184 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004185 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004186 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 +02004187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004189 }
4190 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004191 else if (!strcmp(args[0], "tcp-check")) {
4192 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4193 err_code |= ERR_WARN;
4194
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004195 if (strcmp(args[1], "connect") == 0) {
4196 const char *ptr_arg;
4197 int cur_arg;
4198 struct tcpcheck_rule *tcpcheck;
4199 struct list *l;
4200
4201 /* check if first rule is also a 'connect' action */
4202 l = (struct list *)&curproxy->tcpcheck_rules;
4203 if (l->p != l->n) {
4204 tcpcheck = (struct tcpcheck_rule *)l->n;
4205 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4206 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4207 file, linenum);
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
4211 }
4212
4213 cur_arg = 2;
4214 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4215 tcpcheck->action = TCPCHK_ACT_CONNECT;
4216
4217 /* parsing each parameters to fill up the rule */
4218 while (*(ptr_arg = args[cur_arg])) {
4219 /* tcp port */
4220 if (strcmp(args[cur_arg], "port") == 0) {
4221 if ( (atol(args[cur_arg + 1]) > 65535) ||
4222 (atol(args[cur_arg + 1]) < 1) ){
4223 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4224 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
4227 }
4228 tcpcheck->port = atol(args[cur_arg + 1]);
4229 cur_arg += 2;
4230 }
4231 /* send proxy protocol */
4232 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4233 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4234 cur_arg++;
4235 }
4236#ifdef USE_OPENSSL
4237 else if (strcmp(args[cur_arg], "ssl") == 0) {
4238 curproxy->options |= PR_O_TCPCHK_SSL;
4239 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4240 cur_arg++;
4241 }
4242#endif /* USE_OPENSSL */
4243 else {
4244#ifdef USE_OPENSSL
4245 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4246#else /* USE_OPENSSL */
4247 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4248#endif /* USE_OPENSSL */
4249 file, linenum, args[0], args[1], args[cur_arg]);
4250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
4252 }
4253
4254 }
4255
4256 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4257 }
4258 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004259 if (! *(args[2]) ) {
4260 /* SEND string expected */
4261 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4262 file, linenum, args[0], args[1], args[2]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 } else {
4266 struct tcpcheck_rule *tcpcheck;
4267
4268 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4269
4270 tcpcheck->action = TCPCHK_ACT_SEND;
4271 tcpcheck->string_len = strlen(args[2]);
4272 tcpcheck->string = strdup(args[2]);
4273 tcpcheck->expect_regex = NULL;
4274
4275 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4276 }
4277 }
4278 else if (strcmp(args[1], "send-binary") == 0) {
4279 if (! *(args[2]) ) {
4280 /* SEND binary string expected */
4281 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4282 file, linenum, args[0], args[1], args[2]);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 } else {
4286 struct tcpcheck_rule *tcpcheck;
4287 char *err = NULL;
4288
4289 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4290
4291 tcpcheck->action = TCPCHK_ACT_SEND;
4292 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4293 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4294 file, linenum, args[0], args[1], args[2], err);
4295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298 tcpcheck->expect_regex = NULL;
4299
4300 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4301 }
4302 }
4303 else if (strcmp(args[1], "expect") == 0) {
4304 const char *ptr_arg;
4305 int cur_arg;
4306 int inverse = 0;
4307
4308 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4309 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
4312 }
4313
4314 cur_arg = 2;
4315 /* consider exclamation marks, sole or at the beginning of a word */
4316 while (*(ptr_arg = args[cur_arg])) {
4317 while (*ptr_arg == '!') {
4318 inverse = !inverse;
4319 ptr_arg++;
4320 }
4321 if (*ptr_arg)
4322 break;
4323 cur_arg++;
4324 }
4325 /* now ptr_arg points to the beginning of a word past any possible
4326 * exclamation mark, and cur_arg is the argument which holds this word.
4327 */
4328 if (strcmp(ptr_arg, "binary") == 0) {
4329 if (!*(args[cur_arg + 1])) {
4330 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4331 file, linenum, args[0], args[1], ptr_arg);
4332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 struct tcpcheck_rule *tcpcheck;
4336 char *err = NULL;
4337
4338 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4339
4340 tcpcheck->action = TCPCHK_ACT_EXPECT;
4341 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4342 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4343 file, linenum, args[0], args[1], args[2], err);
4344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
4346 }
4347 tcpcheck->expect_regex = NULL;
4348 tcpcheck->inverse = inverse;
4349
4350 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4351 }
4352 else if (strcmp(ptr_arg, "string") == 0) {
4353 if (!*(args[cur_arg + 1])) {
4354 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4355 file, linenum, args[0], args[1], ptr_arg);
4356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
4358 }
4359 struct tcpcheck_rule *tcpcheck;
4360
4361 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4362
4363 tcpcheck->action = TCPCHK_ACT_EXPECT;
4364 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4365 tcpcheck->string = strdup(args[cur_arg + 1]);
4366 tcpcheck->expect_regex = NULL;
4367 tcpcheck->inverse = inverse;
4368
4369 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4370 }
4371 else if (strcmp(ptr_arg, "rstring") == 0) {
4372 if (!*(args[cur_arg + 1])) {
4373 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4374 file, linenum, args[0], args[1], ptr_arg);
4375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
4377 }
4378 struct tcpcheck_rule *tcpcheck;
4379
4380 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4381
4382 tcpcheck->action = TCPCHK_ACT_EXPECT;
4383 tcpcheck->string_len = 0;
4384 tcpcheck->string = NULL;
4385 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4386 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4387 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4388 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
4392 tcpcheck->inverse = inverse;
4393
4394 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4395 }
4396 else {
4397 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4398 file, linenum, args[0], args[1], ptr_arg);
4399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
4401 }
4402 }
4403 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004404 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407 }
4408 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004409 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004410 if (curproxy == &defproxy) {
4411 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004414 }
4415
Willy Tarreaub80c2302007-11-30 20:51:32 +01004416 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004418
4419 if (strcmp(args[1], "fail") == 0) {
4420 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004421 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004422 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4423 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004426 }
4427
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004428 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4429 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4430 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004433 }
4434 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4435 }
4436 else {
4437 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004440 }
4441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442#ifdef TPROXY
4443 else if (!strcmp(args[0], "transparent")) {
4444 /* enable transparent proxy connections */
4445 curproxy->options |= PR_O_TRANSP;
4446 }
4447#endif
4448 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004449 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004451
Willy Tarreaubaaee002006-06-26 02:48:02 +02004452 if (*(args[1]) == 0) {
4453 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004454 err_code |= ERR_ALERT | ERR_FATAL;
4455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004456 }
4457 curproxy->maxconn = atol(args[1]);
4458 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004459 else if (!strcmp(args[0], "backlog")) { /* backlog */
4460 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004462
4463 if (*(args[1]) == 0) {
4464 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004467 }
4468 curproxy->backlog = atol(args[1]);
4469 }
Willy Tarreau86034312006-12-29 00:10:33 +01004470 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004471 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004472 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004473
Willy Tarreau86034312006-12-29 00:10:33 +01004474 if (*(args[1]) == 0) {
4475 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004478 }
4479 curproxy->fullconn = atol(args[1]);
4480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4482 if (*(args[1]) == 0) {
4483 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004487 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4488 if (err) {
4489 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4490 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004493 }
4494 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 }
4496 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004497 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004498 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004499 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004500
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 if (curproxy == &defproxy) {
4502 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004506 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004508
Willy Tarreau902636f2013-03-10 19:44:48 +01004509 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004510 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004511 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004512 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004513 goto out;
4514 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004515
4516 proto = protocol_by_family(sk->ss_family);
4517 if (!proto || !proto->connect) {
4518 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4519 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
4522 }
4523
4524 if (port1 != port2) {
4525 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4526 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004530
4531 if (!port1) {
4532 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4533 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
4536 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004537
Willy Tarreaud5191e72010-02-09 20:50:45 +01004538 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004539 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 }
4541 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004542 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004544
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004545 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4546 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004550 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004551 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004552 /**
4553 * The syntax for hash-type config element is
4554 * hash-type {map-based|consistent} [[<algo>] avalanche]
4555 *
4556 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4557 */
4558 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004559
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004560 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4561 err_code |= ERR_WARN;
4562
4563 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004564 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4565 }
4566 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004567 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4568 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004569 else if (strcmp(args[1], "avalanche") == 0) {
4570 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]);
4571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004573 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004574 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004575 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
4578 }
Bhaskar98634f02013-10-29 23:30:51 -04004579
4580 /* set the hash function to use */
4581 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004582 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004583 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004584
4585 /* if consistent with no argument, then avalanche modifier is also applied */
4586 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4587 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004588 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004589 /* set the hash function */
4590 if (!strcmp(args[2], "sdbm")) {
4591 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4592 }
4593 else if (!strcmp(args[2], "djb2")) {
4594 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004595 } else if (!strcmp(args[2], "wt6")) {
4596 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004597 }
4598 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004599 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 -05004600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
4602 }
4603
4604 /* set the hash modifier */
4605 if (!strcmp(args[3], "avalanche")) {
4606 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4607 }
4608 else if (*args[3]) {
4609 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004613 }
William Lallemanda73203e2012-03-12 12:48:57 +01004614 }
William Lallemanda73203e2012-03-12 12:48:57 +01004615 else if (strcmp(args[0], "unique-id-format") == 0) {
4616 if (!*(args[1])) {
4617 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
William Lallemand3203ff42012-11-11 17:30:56 +01004621 if (*(args[2])) {
4622 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
4625 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004626 free(curproxy->conf.uniqueid_format_string);
4627 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004628
Willy Tarreau62a61232013-04-12 18:13:46 +02004629 free(curproxy->conf.uif_file);
4630 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4631 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004632 }
William Lallemanda73203e2012-03-12 12:48:57 +01004633
4634 else if (strcmp(args[0], "unique-id-header") == 0) {
4635 if (!*(args[1])) {
4636 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
4639 }
4640 free(curproxy->header_unique_id);
4641 curproxy->header_unique_id = strdup(args[1]);
4642 }
4643
William Lallemand723b73a2012-02-08 16:37:49 +01004644 else if (strcmp(args[0], "log-format") == 0) {
4645 if (!*(args[1])) {
4646 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
William Lallemand3203ff42012-11-11 17:30:56 +01004650 if (*(args[2])) {
4651 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
4654 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004655
Willy Tarreau62a61232013-04-12 18:13:46 +02004656 if (curproxy->conf.logformat_string != default_http_log_format &&
4657 curproxy->conf.logformat_string != default_tcp_log_format &&
4658 curproxy->conf.logformat_string != clf_http_log_format)
4659 free(curproxy->conf.logformat_string);
4660 curproxy->conf.logformat_string = strdup(args[1]);
4661
4662 free(curproxy->conf.lfs_file);
4663 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4664 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004665
4666 /* get a chance to improve log-format error reporting by
4667 * reporting the correct line-number when possible.
4668 */
4669 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4670 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4671 file, linenum, curproxy->id);
4672 err_code |= ERR_WARN;
4673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004674 }
William Lallemand723b73a2012-02-08 16:37:49 +01004675
William Lallemand0f99e342011-10-12 17:50:54 +02004676 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4677 /* delete previous herited or defined syslog servers */
4678 struct logsrv *back;
4679
4680 if (*(args[1]) != 0) {
4681 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4682 err_code |= ERR_ALERT | ERR_FATAL;
4683 goto out;
4684 }
4685
William Lallemand723b73a2012-02-08 16:37:49 +01004686 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4687 LIST_DEL(&tmplogsrv->list);
4688 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004689 }
4690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004692 struct logsrv *logsrv;
4693
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004695 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004696 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004697 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004698 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004699 LIST_INIT(&node->list);
4700 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 }
4703 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004704 struct sockaddr_storage *sk;
4705 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004706
4707 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708
William Lallemand0f99e342011-10-12 17:50:54 +02004709 logsrv->facility = get_log_facility(args[2]);
4710 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 }
4716
William Lallemand0f99e342011-10-12 17:50:54 +02004717 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004719 logsrv->level = get_log_level(args[3]);
4720 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724
Willy Tarreaubaaee002006-06-26 02:48:02 +02004725 }
4726 }
4727
William Lallemand0f99e342011-10-12 17:50:54 +02004728 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004729 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004730 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004731 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004732 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
4735
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004736 }
4737 }
4738
Willy Tarreau902636f2013-03-10 19:44:48 +01004739 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004740 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004741 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004742 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004743 goto out;
4744 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004745
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004746 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004747
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004748 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004749 if (port1 != port2) {
4750 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4751 file, linenum, args[0], args[1]);
4752 err_code |= ERR_ALERT | ERR_FATAL;
4753 goto out;
4754 }
4755
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004756 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004757 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 }
William Lallemand0f99e342011-10-12 17:50:54 +02004759
4760 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
4762 else {
4763 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4764 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
4768 }
4769 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004770 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004771 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004772 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004773 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004774
Willy Tarreau977b8e42006-12-29 14:19:17 +01004775 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004776 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004777
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004779 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4780 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004781 err_code |= ERR_ALERT | ERR_FATAL;
4782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004784
4785 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004786 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4787 free(curproxy->conn_src.iface_name);
4788 curproxy->conn_src.iface_name = NULL;
4789 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004790
Willy Tarreau902636f2013-03-10 19:44:48 +01004791 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004792 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004793 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004794 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004795 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004796 goto out;
4797 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004798
4799 proto = protocol_by_family(sk->ss_family);
4800 if (!proto || !proto->connect) {
4801 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004802 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
4805 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004806
4807 if (port1 != port2) {
4808 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4809 file, linenum, args[0], args[1]);
4810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
4812 }
4813
Willy Tarreauef9a3602012-12-08 22:29:20 +01004814 curproxy->conn_src.source_addr = *sk;
4815 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004816
4817 cur_arg = 2;
4818 while (*(args[cur_arg])) {
4819 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004820#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4821#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02004822 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004823 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4824 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004827 }
4828#endif
4829 if (!*args[cur_arg + 1]) {
4830 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4831 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004832 err_code |= ERR_ALERT | ERR_FATAL;
4833 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004834 }
4835
4836 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004837 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4838 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004839 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004840 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4841 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004842 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4843 char *name, *end;
4844
4845 name = args[cur_arg+1] + 7;
4846 while (isspace(*name))
4847 name++;
4848
4849 end = name;
4850 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4851 end++;
4852
Willy Tarreauef9a3602012-12-08 22:29:20 +01004853 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4854 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4855 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4856 curproxy->conn_src.bind_hdr_len = end - name;
4857 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4858 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4859 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004860
4861 /* now look for an occurrence number */
4862 while (isspace(*end))
4863 end++;
4864 if (*end == ',') {
4865 end++;
4866 name = end;
4867 if (*end == '-')
4868 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004869 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004870 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004871 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004872 }
4873
Willy Tarreauef9a3602012-12-08 22:29:20 +01004874 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004875 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4876 " occurrences values smaller than %d.\n",
4877 file, linenum, MAX_HDR_HISTORY);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004881 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004882 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004883
Willy Tarreau902636f2013-03-10 19:44:48 +01004884 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004885 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004886 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004887 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004888 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004889 goto out;
4890 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004891
4892 proto = protocol_by_family(sk->ss_family);
4893 if (!proto || !proto->connect) {
4894 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4895 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
4898 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004899
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004900 if (port1 != port2) {
4901 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4902 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004903 err_code |= ERR_ALERT | ERR_FATAL;
4904 goto out;
4905 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004906 curproxy->conn_src.tproxy_addr = *sk;
4907 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004908 }
4909 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004910#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004911 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004912#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004913#else /* no TPROXY support */
4914 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004915 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004918#endif
4919 cur_arg += 2;
4920 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004921 }
4922
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004923 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4924#ifdef SO_BINDTODEVICE
4925 if (!*args[cur_arg + 1]) {
4926 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4927 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004930 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004931 free(curproxy->conn_src.iface_name);
4932 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4933 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004934 global.last_checks |= LSTCHK_NETADM;
4935#else
4936 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4937 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004940#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004941 cur_arg += 2;
4942 continue;
4943 }
4944 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004945 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004950 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4951 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4952 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4959 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963
4964 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004965 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004966 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
4970 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004972 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004973 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
4977 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004979 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004980 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983 }
4984 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004986 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004987 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
4991 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004993 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004994 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004998 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005000 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005001 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005003 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005004 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005005 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005007 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005008 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005010 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005011
5012 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5013 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 +01005014 }
5015 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005016 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005017 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005018 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005020 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005021
5022 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5023 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 +01005024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5028 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032
5033 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005034 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005035 args[0], args[1], args[2], (const char **)args+3);
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], "reqidel")) { /* delete request header from a regex ignoring case */
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_REMOVE, REG_ICASE,
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], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
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_DENY, REG_ICASE,
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], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, REG_ICASE,
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 }
5060 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
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_ALLOW, REG_ICASE,
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 Tarreaubaaee002006-06-26 02:48:02 +02005066 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005067 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring 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_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005070 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005072 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005075 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005076
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 if (curproxy == &defproxy) {
5078 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_ALERT | ERR_FATAL;
5080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005082 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 if (*(args[1]) == 0) {
5086 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005090
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005091 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005092 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5093 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5094 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
5097 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005098 err_code |= warnif_cond_conflicts(cond,
5099 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5100 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005101 }
5102 else if (*args[2]) {
5103 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5104 file, linenum, args[0], args[2]);
5105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
5107 }
5108
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005109 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005110 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005111 wl->s = strdup(args[1]);
5112 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005113 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
5115 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5118 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005122
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_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005125 args[0], args[1], args[2], (const char **)args+3);
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 }
5129 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
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_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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 Tarreaubaaee002006-06-26 02:48:02 +02005135 }
5136 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005138 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005139 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5146 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
5150
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005152 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005153 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
5157 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005159 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005160 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 }
5164 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005166 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005167 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005170 }
5171 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005172 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005173
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 if (curproxy == &defproxy) {
5175 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005179 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005180 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 if (*(args[1]) == 0) {
5183 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 }
5187
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005188 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005189 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5190 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5191 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005195 err_code |= warnif_cond_conflicts(cond,
5196 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5197 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005198 }
5199 else if (*args[2]) {
5200 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5201 file, linenum, args[0], args[2]);
5202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005206 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005207 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005208 wl->s = strdup(args[1]);
5209 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211 else if (!strcmp(args[0], "errorloc") ||
5212 !strcmp(args[0], "errorloc302") ||
5213 !strcmp(args[0], "errorloc303")) { /* error location */
5214 int errnum, errlen;
5215 char *err;
5216
Willy Tarreau977b8e42006-12-29 14:19:17 +01005217 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005218 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005219
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005221 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 }
5225
5226 errnum = atol(args[1]);
5227 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005228 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5229 err = malloc(errlen);
5230 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005232 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5233 err = malloc(errlen);
5234 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
5236
Willy Tarreau0f772532006-12-23 20:51:41 +01005237 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5238 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005239 chunk_destroy(&curproxy->errmsg[rc]);
5240 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005241 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005244
5245 if (rc >= HTTP_ERR_SIZE) {
5246 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5247 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 free(err);
5249 }
5250 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005251 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5252 int errnum, errlen, fd;
5253 char *err;
5254 struct stat stat;
5255
5256 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005258
5259 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005260 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005263 }
5264
5265 fd = open(args[2], O_RDONLY);
5266 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5267 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5268 file, linenum, args[2], args[1]);
5269 if (fd >= 0)
5270 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005273 }
5274
Willy Tarreau27a674e2009-08-17 07:23:33 +02005275 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005276 errlen = stat.st_size;
5277 } else {
5278 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005279 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005280 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005281 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005282 }
5283
5284 err = malloc(errlen); /* malloc() must succeed during parsing */
5285 errnum = read(fd, err, errlen);
5286 if (errnum != errlen) {
5287 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5288 file, linenum, args[2], args[1]);
5289 close(fd);
5290 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005293 }
5294 close(fd);
5295
5296 errnum = atol(args[1]);
5297 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5298 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005299 chunk_destroy(&curproxy->errmsg[rc]);
5300 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005301 break;
5302 }
5303 }
5304
5305 if (rc >= HTTP_ERR_SIZE) {
5306 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5307 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005308 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005309 free(err);
5310 }
5311 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005312 else if (!strcmp(args[0], "compression")) {
5313 struct comp *comp;
5314 if (curproxy->comp == NULL) {
5315 comp = calloc(1, sizeof(struct comp));
5316 curproxy->comp = comp;
5317 } else {
5318 comp = curproxy->comp;
5319 }
5320
5321 if (!strcmp(args[1], "algo")) {
5322 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005323 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005324
William Lallemand82fe75c2012-10-23 10:25:10 +02005325 cur_arg = 2;
5326 if (!*args[cur_arg]) {
5327 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5328 file, linenum, args[0]);
5329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
5331 }
5332 while (*(args[cur_arg])) {
5333 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5334 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5335 file, linenum, args[0], args[cur_arg]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
William Lallemand552df672012-11-07 13:21:47 +01005339 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5340 curproxy->comp->algos->end(&ctx);
5341 } else {
5342 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5343 file, linenum, args[0], args[cur_arg]);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005347 cur_arg ++;
5348 continue;
5349 }
5350 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005351 else if (!strcmp(args[1], "offload")) {
5352 comp->offload = 1;
5353 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005354 else if (!strcmp(args[1], "type")) {
5355 int cur_arg;
5356 cur_arg = 2;
5357 if (!*args[cur_arg]) {
5358 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5359 file, linenum, args[0]);
5360 err_code |= ERR_ALERT | ERR_FATAL;
5361 goto out;
5362 }
5363 while (*(args[cur_arg])) {
5364 comp_append_type(comp, args[cur_arg]);
5365 cur_arg ++;
5366 continue;
5367 }
5368 }
5369 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005370 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005371 file, linenum, args[0]);
5372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
5374 }
5375 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005377 struct cfg_kw_list *kwl;
5378 int index;
5379
5380 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5381 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5382 if (kwl->kw[index].section != CFG_LISTEN)
5383 continue;
5384 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5385 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005386 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005387 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005388 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005391 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005392 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005393 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005394 err_code |= ERR_WARN;
5395 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005396 }
Willy Tarreau93893792009-07-23 13:19:11 +02005397 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005398 }
5399 }
5400 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005401
Willy Tarreau6daf3432008-01-22 16:44:08 +01005402 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 }
Willy Tarreau93893792009-07-23 13:19:11 +02005406 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005407 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005408 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409}
5410
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005411int
5412cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5413{
5414
5415 int err_code = 0;
5416 const char *err;
5417
5418 if (!strcmp(args[0], "userlist")) { /* new userlist */
5419 struct userlist *newul;
5420
5421 if (!*args[1]) {
5422 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5423 file, linenum, args[0]);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
5427
5428 err = invalid_char(args[1]);
5429 if (err) {
5430 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5431 file, linenum, *err, args[0], args[1]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435
5436 for (newul = userlist; newul; newul = newul->next)
5437 if (!strcmp(newul->name, args[1])) {
5438 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5439 file, linenum, args[1]);
5440 err_code |= ERR_WARN;
5441 goto out;
5442 }
5443
5444 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5445 if (!newul) {
5446 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5447 err_code |= ERR_ALERT | ERR_ABORT;
5448 goto out;
5449 }
5450
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005451 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005452 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005453 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5454 err_code |= ERR_ALERT | ERR_ABORT;
5455 goto out;
5456 }
5457
5458 newul->next = userlist;
5459 userlist = newul;
5460
5461 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005462 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005463 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005464 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005465
5466 if (!*args[1]) {
5467 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5468 file, linenum, args[0]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472
5473 err = invalid_char(args[1]);
5474 if (err) {
5475 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5476 file, linenum, *err, args[0], args[1]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005481 for (ag = userlist->groups; ag; ag = ag->next)
5482 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005483 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5484 file, linenum, args[1], userlist->name);
5485 err_code |= ERR_ALERT;
5486 goto out;
5487 }
5488
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005489 ag = calloc(1, sizeof(*ag));
5490 if (!ag) {
5491 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5492 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005493 goto out;
5494 }
5495
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005496 ag->name = strdup(args[1]);
5497 if (!ag) {
5498 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5499 err_code |= ERR_ALERT | ERR_ABORT;
5500 goto out;
5501 }
5502
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005503 cur_arg = 2;
5504
5505 while (*args[cur_arg]) {
5506 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005507 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005508 cur_arg += 2;
5509 continue;
5510 } else {
5511 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5512 file, linenum, args[0]);
5513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
5515 }
5516 }
5517
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005518 ag->next = userlist->groups;
5519 userlist->groups = ag;
5520
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005521 } else if (!strcmp(args[0], "user")) { /* new user */
5522 struct auth_users *newuser;
5523 int cur_arg;
5524
5525 if (!*args[1]) {
5526 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5527 file, linenum, args[0]);
5528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
5530 }
5531
5532 for (newuser = userlist->users; newuser; newuser = newuser->next)
5533 if (!strcmp(newuser->user, args[1])) {
5534 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5535 file, linenum, args[1], userlist->name);
5536 err_code |= ERR_ALERT;
5537 goto out;
5538 }
5539
5540 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5541 if (!newuser) {
5542 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5543 err_code |= ERR_ALERT | ERR_ABORT;
5544 goto out;
5545 }
5546
5547 newuser->user = strdup(args[1]);
5548
5549 newuser->next = userlist->users;
5550 userlist->users = newuser;
5551
5552 cur_arg = 2;
5553
5554 while (*args[cur_arg]) {
5555 if (!strcmp(args[cur_arg], "password")) {
5556#ifndef CONFIG_HAP_CRYPT
5557 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5558 file, linenum);
5559 err_code |= ERR_ALERT;
5560#endif
5561 newuser->pass = strdup(args[cur_arg + 1]);
5562 cur_arg += 2;
5563 continue;
5564 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5565 newuser->pass = strdup(args[cur_arg + 1]);
5566 newuser->flags |= AU_O_INSECURE;
5567 cur_arg += 2;
5568 continue;
5569 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005570 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005571 cur_arg += 2;
5572 continue;
5573 } else {
5574 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5575 file, linenum, args[0]);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 }
5579 }
5580 } else {
5581 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5582 err_code |= ERR_ALERT | ERR_FATAL;
5583 }
5584
5585out:
5586 return err_code;
5587}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588
5589/*
5590 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005591 * Returns the error code, 0 if OK, or any combination of :
5592 * - ERR_ABORT: must abort ASAP
5593 * - ERR_FATAL: we can continue parsing but not start the service
5594 * - ERR_WARN: a warning has been emitted
5595 * - ERR_ALERT: an alert has been emitted
5596 * Only the two first ones can stop processing, the two others are just
5597 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005599int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005601 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 FILE *f;
5603 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005604 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005605 struct cfg_section *cs = NULL;
5606 struct cfg_section *ics;
5607
5608 /* Register internal sections */
5609 if (!cfg_register_section("listen", cfg_parse_listen) ||
5610 !cfg_register_section("frontend", cfg_parse_listen) ||
5611 !cfg_register_section("backend", cfg_parse_listen) ||
5612 !cfg_register_section("ruleset", cfg_parse_listen) ||
5613 !cfg_register_section("defaults", cfg_parse_listen) ||
5614 !cfg_register_section("global", cfg_parse_global) ||
5615 !cfg_register_section("userlist", cfg_parse_users) ||
5616 !cfg_register_section("peers", cfg_parse_peers))
5617 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005618
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 if ((f=fopen(file,"r")) == NULL)
5620 return -1;
5621
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005622 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005623 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005624 char *end;
5625 char *args[MAX_LINE_ARGS + 1];
5626 char *line = thisline;
5627
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 linenum++;
5629
5630 end = line + strlen(line);
5631
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005632 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5633 /* Check if we reached the limit and the last char is not \n.
5634 * Watch out for the last line without the terminating '\n'!
5635 */
5636 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005637 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005639 }
5640
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005642 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 line++;
5644
5645 arg = 0;
5646 args[arg] = line;
5647
5648 while (*line && arg < MAX_LINE_ARGS) {
5649 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5650 * C equivalent value. Other combinations left unchanged (eg: \1).
5651 */
5652 if (*line == '\\') {
5653 int skip = 0;
5654 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5655 *line = line[1];
5656 skip = 1;
5657 }
5658 else if (line[1] == 'r') {
5659 *line = '\r';
5660 skip = 1;
5661 }
5662 else if (line[1] == 'n') {
5663 *line = '\n';
5664 skip = 1;
5665 }
5666 else if (line[1] == 't') {
5667 *line = '\t';
5668 skip = 1;
5669 }
5670 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005671 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 unsigned char hex1, hex2;
5673 hex1 = toupper(line[2]) - '0';
5674 hex2 = toupper(line[3]) - '0';
5675 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5676 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5677 *line = (hex1<<4) + hex2;
5678 skip = 3;
5679 }
5680 else {
5681 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
5684 }
5685 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005686 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 end -= skip;
5688 }
5689 line++;
5690 }
5691 else if (*line == '#' || *line == '\n' || *line == '\r') {
5692 /* end of string, end of loop */
5693 *line = 0;
5694 break;
5695 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005696 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005698 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005699 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700 line++;
5701 args[++arg] = line;
5702 }
5703 else {
5704 line++;
5705 }
5706 }
5707
5708 /* empty line */
5709 if (!**args)
5710 continue;
5711
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005712 if (*line) {
5713 /* we had to stop due to too many args.
5714 * Let's terminate the string, print the offending part then cut the
5715 * last arg.
5716 */
5717 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5718 line++;
5719 *line = '\0';
5720
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005721 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005722 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005723 err_code |= ERR_ALERT | ERR_FATAL;
5724 args[arg] = line;
5725 }
5726
Willy Tarreau540abe42007-05-02 20:50:16 +02005727 /* zero out remaining args and ensure that at least one entry
5728 * is zeroed out.
5729 */
5730 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 args[arg] = line;
5732 }
5733
Willy Tarreau3842f002009-06-14 11:39:52 +02005734 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005735 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005736 char *tmp;
5737
Willy Tarreau3842f002009-06-14 11:39:52 +02005738 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005739 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005740 for (arg=0; *args[arg+1]; arg++)
5741 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005742 *tmp = '\0'; // fix the next arg to \0
5743 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005744 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005745 else if (!strcmp(args[0], "default")) {
5746 kwm = KWM_DEF;
5747 for (arg=0; *args[arg+1]; arg++)
5748 args[arg] = args[arg+1]; // shift args after inversion
5749 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005750
William Lallemand0f99e342011-10-12 17:50:54 +02005751 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5752 strcmp(args[0], "log") != 0) {
5753 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005755 }
5756
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005757 /* detect section start */
5758 list_for_each_entry(ics, &sections, list) {
5759 if (strcmp(args[0], ics->section_name) == 0) {
5760 cursection = ics->section_name;
5761 cs = ics;
5762 break;
5763 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005764 }
5765
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005767 if (cs)
5768 err_code |= cs->section_parser(file, linenum, args, kwm);
5769 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005770 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005773
5774 if (err_code & ERR_ABORT)
5775 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005776 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005777 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005779 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005780}
5781
Willy Tarreaubb925012009-07-23 13:36:36 +02005782/*
5783 * Returns the error code, 0 if OK, or any combination of :
5784 * - ERR_ABORT: must abort ASAP
5785 * - ERR_FATAL: we can continue parsing but not start the service
5786 * - ERR_WARN: a warning has been emitted
5787 * - ERR_ALERT: an alert has been emitted
5788 * Only the two first ones can stop processing, the two others are just
5789 * indicators.
5790 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005791int check_config_validity()
5792{
5793 int cfgerr = 0;
5794 struct proxy *curproxy = NULL;
5795 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005796 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005797 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005798 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005800 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 /*
5802 * Now, check for the integrity of all that we have collected.
5803 */
5804
5805 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005806 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807
Willy Tarreau193b8c62012-11-22 00:17:38 +01005808 if (!global.tune.max_http_hdr)
5809 global.tune.max_http_hdr = MAX_HTTP_HDR;
5810
5811 if (!global.tune.cookie_len)
5812 global.tune.cookie_len = CAPTURE_LEN;
5813
5814 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5815
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005816 /* Post initialisation of the users and groups lists. */
5817 err_code = userlist_postinit();
5818 if (err_code != ERR_NONE)
5819 goto out;
5820
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005821 /* first, we will invert the proxy list order */
5822 curproxy = NULL;
5823 while (proxy) {
5824 struct proxy *next;
5825
5826 next = proxy->next;
5827 proxy->next = curproxy;
5828 curproxy = proxy;
5829 if (!next)
5830 break;
5831 proxy = next;
5832 }
5833
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005835 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005836 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005837 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005838 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005839 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005840 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005841 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005842
Willy Tarreau050536d2012-10-04 08:47:34 +02005843 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005844 /* proxy ID not set, use automatic numbering with first
5845 * spare entry starting with next_pxid.
5846 */
5847 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5848 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5849 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005850 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005851 next_pxid++;
5852
Willy Tarreau55ea7572007-06-17 19:56:27 +02005853
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005855 /* ensure we don't keep listeners uselessly bound */
5856 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 curproxy = curproxy->next;
5858 continue;
5859 }
5860
Willy Tarreau102df612014-05-07 23:56:38 +02005861 /* Check multi-process mode compatibility for the current proxy */
5862
5863 if (curproxy->bind_proc) {
5864 /* an explicit bind-process was specified, let's check how many
5865 * processes remain.
5866 */
5867 nbproc = popcount(curproxy->bind_proc);
5868
5869 curproxy->bind_proc &= nbits(global.nbproc);
5870 if (!curproxy->bind_proc && nbproc == 1) {
5871 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);
5872 curproxy->bind_proc = 1;
5873 }
5874 else if (!curproxy->bind_proc && nbproc > 1) {
5875 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);
5876 curproxy->bind_proc = 0;
5877 }
5878 }
5879
Willy Tarreau3d209582014-05-09 17:06:11 +02005880 /* check and reduce the bind-proc of each listener */
5881 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
5882 unsigned long mask;
5883
5884 if (!bind_conf->bind_proc)
5885 continue;
5886
5887 mask = nbits(global.nbproc);
5888 if (curproxy->bind_proc)
5889 mask &= curproxy->bind_proc;
5890 /* mask cannot be null here thanks to the previous checks */
5891
5892 nbproc = popcount(bind_conf->bind_proc);
5893 bind_conf->bind_proc &= mask;
5894
5895 if (!bind_conf->bind_proc && nbproc == 1) {
5896 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",
5897 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5898 bind_conf->bind_proc = mask & ~(mask - 1);
5899 }
5900 else if (!bind_conf->bind_proc && nbproc > 1) {
5901 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",
5902 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5903 bind_conf->bind_proc = 0;
5904 }
5905 }
5906
Willy Tarreau102df612014-05-07 23:56:38 +02005907 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
5908 * We now check how many processes the proxy will effectively run on.
5909 */
5910
5911 nbproc = global.nbproc;
5912 if (curproxy->bind_proc)
5913 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
5914
5915 if (global.nbproc > 1 && curproxy->table.peers.name) {
5916 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
5917 curproxy->id);
5918 cfgerr++;
5919 }
Willy Tarreau16a21472012-11-19 12:39:59 +01005920
Willy Tarreauff01a212009-03-15 13:46:16 +01005921 switch (curproxy->mode) {
5922 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005923 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005924 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005925 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5926 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005927 cfgerr++;
5928 }
5929
5930 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005931 Warning("config : servers will be ignored for %s '%s'.\n",
5932 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005933 break;
5934
5935 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005936 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005937 break;
5938
5939 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005940 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005941 break;
5942 }
5943
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005944 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005945 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005946 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005947 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5948 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005949 cfgerr++;
5950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005952 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005953 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5954 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005955 cfgerr++;
5956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005958 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005959 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5960 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005961 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005962 }
5963 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005964 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005965 /* If no LB algo is set in a backend, and we're not in
5966 * transparent mode, dispatch mode nor proxy mode, we
5967 * want to use balance roundrobin by default.
5968 */
5969 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5970 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 }
5972 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005973
Willy Tarreau1620ec32011-08-06 17:05:02 +02005974 if (curproxy->options & PR_O_DISPATCH)
5975 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5976 else if (curproxy->options & PR_O_HTTP_PROXY)
5977 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5978 else if (curproxy->options & PR_O_TRANSP)
5979 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005980
Willy Tarreau1620ec32011-08-06 17:05:02 +02005981 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5982 if (curproxy->options & PR_O_DISABLE404) {
5983 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5984 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5985 err_code |= ERR_WARN;
5986 curproxy->options &= ~PR_O_DISABLE404;
5987 }
5988 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5989 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5990 "send-state", proxy_type_str(curproxy), curproxy->id);
5991 err_code |= ERR_WARN;
5992 curproxy->options &= ~PR_O2_CHK_SNDST;
5993 }
Willy Tarreauef781042010-01-27 11:53:01 +01005994 }
5995
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005996 /* if a default backend was specified, let's find it */
5997 if (curproxy->defbe.name) {
5998 struct proxy *target;
5999
Alex Williams96532db2009-11-01 21:27:13 -05006000 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006001 if (!target) {
6002 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6003 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006004 cfgerr++;
6005 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006006 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6007 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006008 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006009 } else {
6010 free(curproxy->defbe.name);
6011 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006012 /* we force the backend to be present on at least all of
6013 * the frontend's processes.
6014 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006015 if (target->bind_proc)
6016 target->bind_proc = curproxy->bind_proc ?
6017 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006018
6019 /* Emit a warning if this proxy also has some servers */
6020 if (curproxy->srv) {
6021 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6022 curproxy->id);
6023 err_code |= ERR_WARN;
6024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 }
6026 }
6027
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006028 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006029 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6030 /* map jump target for ACT_SETBE in req_rep chain */
6031 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006032 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006033 struct proxy *target;
6034
Willy Tarreaua496b602006-12-17 23:15:24 +01006035 if (exp->action != ACT_SETBE)
6036 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006037
Alex Williams96532db2009-11-01 21:27:13 -05006038 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006039 if (!target) {
6040 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6041 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006042 cfgerr++;
6043 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006044 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6045 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006046 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006047 } else {
6048 free((void *)exp->replace);
6049 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006050 /* we force the backend to be present on at least all of
6051 * the frontend's processes.
6052 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006053 if (target->bind_proc)
6054 target->bind_proc = curproxy->bind_proc ?
6055 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006056 }
6057 }
6058 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006059
6060 /* find the target proxy for 'use_backend' rules */
6061 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006062 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006063 struct logformat_node *node;
6064 char *pxname;
6065
6066 /* Try to parse the string as a log format expression. If the result
6067 * of the parsing is only one entry containing a simple string, then
6068 * it's a standard string corresponding to a static rule, thus the
6069 * parsing is cancelled and be.name is restored to be resolved.
6070 */
6071 pxname = rule->be.name;
6072 LIST_INIT(&rule->be.expr);
6073 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6074 curproxy->conf.args.file, curproxy->conf.args.line);
6075 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6076
6077 if (!LIST_ISEMPTY(&rule->be.expr)) {
6078 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6079 rule->dynamic = 1;
6080 free(pxname);
6081 continue;
6082 }
6083 /* simple string: free the expression and fall back to static rule */
6084 free(node->arg);
6085 free(node);
6086 }
6087
6088 rule->dynamic = 0;
6089 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006090
Alex Williams96532db2009-11-01 21:27:13 -05006091 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006092
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006093 if (!target) {
6094 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6095 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006096 cfgerr++;
6097 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006098 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6099 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006100 cfgerr++;
6101 } else {
6102 free((void *)rule->be.name);
6103 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006104 /* we force the backend to be present on at least all of
6105 * the frontend's processes.
6106 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006107 if (target->bind_proc)
6108 target->bind_proc = curproxy->bind_proc ?
6109 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006110 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006111 }
6112
6113 /* find the target proxy for 'use_backend' rules */
6114 list_for_each_entry(srule, &curproxy->server_rules, list) {
6115 struct server *target = findserver(curproxy, srule->srv.name);
6116
6117 if (!target) {
6118 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6119 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6120 cfgerr++;
6121 continue;
6122 }
6123 free((void *)srule->srv.name);
6124 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006125 }
6126
Emeric Brunb982a3d2010-01-04 15:45:53 +01006127 /* find the target table for 'stick' rules */
6128 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6129 struct proxy *target;
6130
Emeric Brun1d33b292010-01-04 15:47:17 +01006131 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6132 if (mrule->flags & STK_IS_STORE)
6133 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6134
Emeric Brunb982a3d2010-01-04 15:45:53 +01006135 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006136 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006137 else
6138 target = curproxy;
6139
6140 if (!target) {
6141 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6142 curproxy->id, mrule->table.name);
6143 cfgerr++;
6144 }
6145 else if (target->table.size == 0) {
6146 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6147 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6148 cfgerr++;
6149 }
Willy Tarreau12785782012-04-27 21:37:17 +02006150 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6151 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006152 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6153 cfgerr++;
6154 }
6155 else {
6156 free((void *)mrule->table.name);
6157 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006158 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006159 }
6160 }
6161
6162 /* find the target table for 'store response' rules */
6163 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6164 struct proxy *target;
6165
Emeric Brun1d33b292010-01-04 15:47:17 +01006166 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6167
Emeric Brunb982a3d2010-01-04 15:45:53 +01006168 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006169 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006170 else
6171 target = curproxy;
6172
6173 if (!target) {
6174 Alert("Proxy '%s': unable to find store table '%s'.\n",
6175 curproxy->id, mrule->table.name);
6176 cfgerr++;
6177 }
6178 else if (target->table.size == 0) {
6179 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6180 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6181 cfgerr++;
6182 }
Willy Tarreau12785782012-04-27 21:37:17 +02006183 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6184 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006185 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6186 cfgerr++;
6187 }
6188 else {
6189 free((void *)mrule->table.name);
6190 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006191 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006192 }
6193 }
6194
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006195 /* find the target table for 'tcp-request' layer 4 rules */
6196 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6197 struct proxy *target;
6198
Willy Tarreaub4c84932013-07-23 19:15:30 +02006199 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006200 continue;
6201
6202 if (trule->act_prm.trk_ctr.table.n)
6203 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6204 else
6205 target = curproxy;
6206
6207 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006208 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6209 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006210 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006211 cfgerr++;
6212 }
6213 else if (target->table.size == 0) {
6214 Alert("Proxy '%s': table '%s' used but not configured.\n",
6215 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6216 cfgerr++;
6217 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006218 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6219 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6220 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 +01006221 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006222 cfgerr++;
6223 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006224 else {
6225 free(trule->act_prm.trk_ctr.table.n);
6226 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006227 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006228 * to pass a list of counters to track and allocate them right here using
6229 * stktable_alloc_data_type().
6230 */
6231 }
6232 }
6233
Willy Tarreaud1f96522010-08-03 19:34:32 +02006234 /* find the target table for 'tcp-request' layer 6 rules */
6235 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6236 struct proxy *target;
6237
Willy Tarreaub4c84932013-07-23 19:15:30 +02006238 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006239 continue;
6240
6241 if (trule->act_prm.trk_ctr.table.n)
6242 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6243 else
6244 target = curproxy;
6245
6246 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006247 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6248 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006249 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006250 cfgerr++;
6251 }
6252 else if (target->table.size == 0) {
6253 Alert("Proxy '%s': table '%s' used but not configured.\n",
6254 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6255 cfgerr++;
6256 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006257 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6258 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6259 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 +01006260 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006261 cfgerr++;
6262 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006263 else {
6264 free(trule->act_prm.trk_ctr.table.n);
6265 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006266 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006267 * to pass a list of counters to track and allocate them right here using
6268 * stktable_alloc_data_type().
6269 */
6270 }
6271 }
6272
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006273 /* move any "block" rules at the beginning of the http-request rules */
6274 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6275 /* insert block_rules into http_req_rules at the beginning */
6276 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6277 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6278 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6279 curproxy->http_req_rules.n = curproxy->block_rules.n;
6280 LIST_INIT(&curproxy->block_rules);
6281 }
6282
Emeric Brun32da3c42010-09-23 18:39:19 +02006283 if (curproxy->table.peers.name) {
6284 struct peers *curpeers = peers;
6285
6286 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6287 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6288 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006289 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006290 break;
6291 }
6292 }
6293
6294 if (!curpeers) {
6295 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6296 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006297 free((void *)curproxy->table.peers.name);
6298 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006299 cfgerr++;
6300 }
6301 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006302 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6303 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006304 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006305 cfgerr++;
6306 }
6307 }
6308
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006309 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006310 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006311 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6312 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6313 "proxy", curproxy->id);
6314 cfgerr++;
6315 goto out_uri_auth_compat;
6316 }
6317
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006318 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006319 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006320 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006321 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006322
Willy Tarreau95fa4692010-02-01 13:05:50 +01006323 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6324 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006325
6326 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006327 uri_auth_compat_req[i++] = "realm";
6328 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6329 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006330
Willy Tarreau95fa4692010-02-01 13:05:50 +01006331 uri_auth_compat_req[i++] = "unless";
6332 uri_auth_compat_req[i++] = "{";
6333 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6334 uri_auth_compat_req[i++] = "}";
6335 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006336
Willy Tarreauff011f22011-01-06 17:51:27 +01006337 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6338 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006339 cfgerr++;
6340 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006341 }
6342
Willy Tarreauff011f22011-01-06 17:51:27 +01006343 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006344
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006345 if (curproxy->uri_auth->auth_realm) {
6346 free(curproxy->uri_auth->auth_realm);
6347 curproxy->uri_auth->auth_realm = NULL;
6348 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006349
6350 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006351 }
6352out_uri_auth_compat:
6353
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006354 /* compile the log format */
6355 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006356 if (curproxy->conf.logformat_string != default_http_log_format &&
6357 curproxy->conf.logformat_string != default_tcp_log_format &&
6358 curproxy->conf.logformat_string != clf_http_log_format)
6359 free(curproxy->conf.logformat_string);
6360 curproxy->conf.logformat_string = NULL;
6361 free(curproxy->conf.lfs_file);
6362 curproxy->conf.lfs_file = NULL;
6363 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006364 }
6365
Willy Tarreau62a61232013-04-12 18:13:46 +02006366 if (curproxy->conf.logformat_string) {
6367 curproxy->conf.args.ctx = ARGC_LOG;
6368 curproxy->conf.args.file = curproxy->conf.lfs_file;
6369 curproxy->conf.args.line = curproxy->conf.lfs_line;
6370 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006371 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006372 curproxy->conf.args.file = NULL;
6373 curproxy->conf.args.line = 0;
6374 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006375
Willy Tarreau62a61232013-04-12 18:13:46 +02006376 if (curproxy->conf.uniqueid_format_string) {
6377 curproxy->conf.args.ctx = ARGC_UIF;
6378 curproxy->conf.args.file = curproxy->conf.uif_file;
6379 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006380 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006381 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6382 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006383 curproxy->conf.args.file = NULL;
6384 curproxy->conf.args.line = 0;
6385 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006386
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006387 /* only now we can check if some args remain unresolved.
6388 * This must be done after the users and groups resolution.
6389 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006390 cfgerr += smp_resolve_args(curproxy);
6391 if (!cfgerr)
6392 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006393
Willy Tarreau2738a142006-07-08 17:28:09 +02006394 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006395 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006396 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006397 (!curproxy->timeout.connect ||
6398 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006399 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006400 " | While not properly invalid, you will certainly encounter various problems\n"
6401 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006402 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006403 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006404 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006405 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006406
Willy Tarreau1fa31262007-12-03 00:36:16 +01006407 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6408 * We must still support older configurations, so let's find out whether those
6409 * parameters have been set or must be copied from contimeouts.
6410 */
6411 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006412 if (!curproxy->timeout.tarpit ||
6413 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006414 /* tarpit timeout not set. We search in the following order:
6415 * default.tarpit, curr.connect, default.connect.
6416 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006417 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006418 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006419 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006420 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006421 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006422 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006423 }
6424 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006425 (!curproxy->timeout.queue ||
6426 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006427 /* queue timeout not set. We search in the following order:
6428 * default.queue, curr.connect, default.connect.
6429 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006430 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006431 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006432 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006433 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006434 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006435 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006436 }
6437 }
6438
Willy Tarreau1620ec32011-08-06 17:05:02 +02006439 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006440 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6441 curproxy->check_req = (char *)malloc(curproxy->check_len);
6442 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006443 }
6444
Willy Tarreau193b8c62012-11-22 00:17:38 +01006445 /* ensure that cookie capture length is not too large */
6446 if (curproxy->capture_len >= global.tune.cookie_len) {
6447 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6448 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6449 err_code |= ERR_WARN;
6450 curproxy->capture_len = global.tune.cookie_len - 1;
6451 }
6452
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006453 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006454 if (curproxy->nb_req_cap) {
6455 if (curproxy->mode == PR_MODE_HTTP) {
6456 curproxy->req_cap_pool = create_pool("ptrcap",
6457 curproxy->nb_req_cap * sizeof(char *),
6458 MEM_F_SHARED);
6459 } else {
6460 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6461 proxy_type_str(curproxy), curproxy->id);
6462 err_code |= ERR_WARN;
6463 curproxy->to_log &= ~LW_REQHDR;
6464 curproxy->nb_req_cap = 0;
6465 }
6466 }
6467
6468 if (curproxy->nb_rsp_cap) {
6469 if (curproxy->mode == PR_MODE_HTTP) {
6470 curproxy->rsp_cap_pool = create_pool("ptrcap",
6471 curproxy->nb_rsp_cap * sizeof(char *),
6472 MEM_F_SHARED);
6473 } else {
6474 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6475 proxy_type_str(curproxy), curproxy->id);
6476 err_code |= ERR_WARN;
6477 curproxy->to_log &= ~LW_REQHDR;
6478 curproxy->nb_rsp_cap = 0;
6479 }
6480 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006481
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 /* first, we will invert the servers list order */
6483 newsrv = NULL;
6484 while (curproxy->srv) {
6485 struct server *next;
6486
6487 next = curproxy->srv->next;
6488 curproxy->srv->next = newsrv;
6489 newsrv = curproxy->srv;
6490 if (!next)
6491 break;
6492 curproxy->srv = next;
6493 }
6494
Willy Tarreau17edc812014-01-03 12:14:34 +01006495 /* Check that no server name conflicts. This causes trouble in the stats.
6496 * We only emit a warning for the first conflict affecting each server,
6497 * in order to avoid combinatory explosion if all servers have the same
6498 * name. We do that only for servers which do not have an explicit ID,
6499 * because these IDs were made also for distinguishing them and we don't
6500 * want to annoy people who correctly manage them.
6501 */
6502 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6503 struct server *other_srv;
6504
6505 if (newsrv->puid)
6506 continue;
6507
6508 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6509 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6510 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6511 newsrv->conf.file, newsrv->conf.line,
6512 proxy_type_str(curproxy), curproxy->id,
6513 newsrv->id, other_srv->conf.line);
6514 break;
6515 }
6516 }
6517 }
6518
Willy Tarreaudd701652010-05-25 23:03:02 +02006519 /* assign automatic UIDs to servers which don't have one yet */
6520 next_id = 1;
6521 newsrv = curproxy->srv;
6522 while (newsrv != NULL) {
6523 if (!newsrv->puid) {
6524 /* server ID not set, use automatic numbering with first
6525 * spare entry starting with next_svid.
6526 */
6527 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6528 newsrv->conf.id.key = newsrv->puid = next_id;
6529 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6530 }
6531 next_id++;
6532 newsrv = newsrv->next;
6533 }
6534
Willy Tarreau20697042007-11-15 23:26:18 +01006535 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006536 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537
Willy Tarreau62c3be22012-01-20 13:12:32 +01006538 /*
6539 * If this server supports a maxconn parameter, it needs a dedicated
6540 * tasks to fill the emptied slots when a connection leaves.
6541 * Also, resolve deferred tracking dependency if needed.
6542 */
6543 newsrv = curproxy->srv;
6544 while (newsrv != NULL) {
6545 if (newsrv->minconn > newsrv->maxconn) {
6546 /* Only 'minconn' was specified, or it was higher than or equal
6547 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6548 * this will avoid further useless expensive computations.
6549 */
6550 newsrv->maxconn = newsrv->minconn;
6551 } else if (newsrv->maxconn && !newsrv->minconn) {
6552 /* minconn was not specified, so we set it to maxconn */
6553 newsrv->minconn = newsrv->maxconn;
6554 }
6555
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006556#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006557 if (newsrv->use_ssl || newsrv->check.use_ssl)
6558 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006559#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006560
Willy Tarreau2f075e92013-12-03 11:11:34 +01006561 /* set the check type on the server */
6562 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6563
Willy Tarreau62c3be22012-01-20 13:12:32 +01006564 if (newsrv->trackit) {
6565 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006566 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006567 char *pname, *sname;
6568
6569 pname = newsrv->trackit;
6570 sname = strrchr(pname, '/');
6571
6572 if (sname)
6573 *sname++ = '\0';
6574 else {
6575 sname = pname;
6576 pname = NULL;
6577 }
6578
6579 if (pname) {
6580 px = findproxy(pname, PR_CAP_BE);
6581 if (!px) {
6582 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6583 proxy_type_str(curproxy), curproxy->id,
6584 newsrv->id, pname);
6585 cfgerr++;
6586 goto next_srv;
6587 }
6588 } else
6589 px = curproxy;
6590
6591 srv = findserver(px, sname);
6592 if (!srv) {
6593 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6594 proxy_type_str(curproxy), curproxy->id,
6595 newsrv->id, sname);
6596 cfgerr++;
6597 goto next_srv;
6598 }
6599
Willy Tarreau32091232014-05-16 13:52:00 +02006600 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6601 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6602 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006603 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006604 "tracking as it does not have any check nor agent enabled.\n",
6605 proxy_type_str(curproxy), curproxy->id,
6606 newsrv->id, px->id, srv->id);
6607 cfgerr++;
6608 goto next_srv;
6609 }
6610
6611 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6612
6613 if (loop) {
6614 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6615 "belongs to a tracking chain looping back to %s/%s.\n",
6616 proxy_type_str(curproxy), curproxy->id,
6617 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006618 cfgerr++;
6619 goto next_srv;
6620 }
6621
6622 if (curproxy != px &&
6623 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6624 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6625 "tracking: disable-on-404 option inconsistency.\n",
6626 proxy_type_str(curproxy), curproxy->id,
6627 newsrv->id, px->id, srv->id);
6628 cfgerr++;
6629 goto next_srv;
6630 }
6631
6632 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006633 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006634 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006635 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006636 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006637 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006638 }
6639
6640 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006641 newsrv->tracknext = srv->trackers;
6642 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006643
6644 free(newsrv->trackit);
6645 newsrv->trackit = NULL;
6646 }
6647 next_srv:
6648 newsrv = newsrv->next;
6649 }
6650
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006651 /* We have to initialize the server lookup mechanism depending
6652 * on what LB algorithm was choosen.
6653 */
6654
6655 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6656 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6657 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006658 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6659 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6660 init_server_map(curproxy);
6661 } else {
6662 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6663 fwrr_init_server_groups(curproxy);
6664 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006665 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006666
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006667 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006668 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6669 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6670 fwlc_init_server_tree(curproxy);
6671 } else {
6672 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6673 fas_init_server_tree(curproxy);
6674 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006675 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006676
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006677 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006678 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6679 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6680 chash_init_server_tree(curproxy);
6681 } else {
6682 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6683 init_server_map(curproxy);
6684 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006685 break;
6686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006687
6688 if (curproxy->options & PR_O_LOGASAP)
6689 curproxy->to_log &= ~LW_BYTES;
6690
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006691 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006692 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006693 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6694 proxy_type_str(curproxy), curproxy->id);
6695 err_code |= ERR_WARN;
6696 }
6697
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006698 if (curproxy->mode != PR_MODE_HTTP) {
6699 int optnum;
6700
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006701 if (curproxy->uri_auth) {
6702 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6703 proxy_type_str(curproxy), curproxy->id);
6704 err_code |= ERR_WARN;
6705 curproxy->uri_auth = NULL;
6706 }
6707
Willy Tarreau87cf5142011-08-19 22:57:24 +02006708 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006709 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6710 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6711 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006712 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006713 }
6714
6715 if (curproxy->options & PR_O_ORGTO) {
6716 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6717 "originalto", proxy_type_str(curproxy), curproxy->id);
6718 err_code |= ERR_WARN;
6719 curproxy->options &= ~PR_O_ORGTO;
6720 }
6721
6722 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6723 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6724 (curproxy->cap & cfg_opts[optnum].cap) &&
6725 (curproxy->options & cfg_opts[optnum].val)) {
6726 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6727 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6728 err_code |= ERR_WARN;
6729 curproxy->options &= ~cfg_opts[optnum].val;
6730 }
6731 }
6732
6733 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6734 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6735 (curproxy->cap & cfg_opts2[optnum].cap) &&
6736 (curproxy->options2 & cfg_opts2[optnum].val)) {
6737 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6738 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6739 err_code |= ERR_WARN;
6740 curproxy->options2 &= ~cfg_opts2[optnum].val;
6741 }
6742 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006743
Pieter Baauwd551fb52013-05-08 22:49:23 +02006744#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006745 if (curproxy->conn_src.bind_hdr_occ) {
6746 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006747 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006748 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006749 err_code |= ERR_WARN;
6750 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006751#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006752 }
6753
Willy Tarreaubaaee002006-06-26 02:48:02 +02006754 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006755 * ensure that we're not cross-dressing a TCP server into HTTP.
6756 */
6757 newsrv = curproxy->srv;
6758 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006759 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006760 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6761 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006762 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006763 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006764
Willy Tarreau0cec3312011-10-31 13:49:26 +01006765 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6766 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6767 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6768 err_code |= ERR_WARN;
6769 }
6770
Willy Tarreauc93cd162014-05-13 15:54:22 +02006771 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006772 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6773 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6774 err_code |= ERR_WARN;
6775 }
6776
Pieter Baauwd551fb52013-05-08 22:49:23 +02006777#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006778 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6779 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006780 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 +01006781 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006782 err_code |= ERR_WARN;
6783 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006784#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006785 newsrv = newsrv->next;
6786 }
6787
Willy Tarreauc1a21672009-08-16 22:37:44 +02006788 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006789 if (!curproxy->accept)
6790 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006791
Willy Tarreauc1a21672009-08-16 22:37:44 +02006792 if (curproxy->tcp_req.inspect_delay ||
6793 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006794 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006795
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006796 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006797 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006798 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006799 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006800
6801 /* both TCP and HTTP must check switching rules */
6802 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6803 }
6804
6805 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006806 if (curproxy->tcp_req.inspect_delay ||
6807 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6808 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6809
Emeric Brun97679e72010-09-23 17:56:44 +02006810 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6811 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6812
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006813 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006814 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006815 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006816 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006817
6818 /* If the backend does requires RDP cookie persistence, we have to
6819 * enable the corresponding analyser.
6820 */
6821 if (curproxy->options2 & PR_O2_RDPC_PRST)
6822 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6823 }
6824
Emeric Brunc52962f2012-11-15 18:28:02 +01006825#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006826 /* Configure SSL for each bind line.
6827 * Note: if configuration fails at some point, the ->ctx member
6828 * remains NULL so that listeners can later detach.
6829 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006830 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006831 int alloc_ctx;
6832
Emeric Brunc52962f2012-11-15 18:28:02 +01006833 if (!bind_conf->is_ssl) {
6834 if (bind_conf->default_ctx) {
6835 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6836 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6837 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006838 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006839 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006840 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006841 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006842 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006843 cfgerr++;
6844 continue;
6845 }
6846
Emeric Brun8dc60392014-05-09 13:52:00 +02006847 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006848 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02006849 if (alloc_ctx == SHCTX_E_INIT_LOCK)
6850 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");
6851 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006852 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02006853 cfgerr++;
6854 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006855 }
6856
Emeric Brunfc0421f2012-09-07 17:30:07 +02006857 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006858 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006859 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006860#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006861
Willy Tarreaue6b98942007-10-29 01:09:36 +01006862 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006863 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006864 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006865 if (!listener->luid) {
6866 /* listener ID not set, use automatic numbering with first
6867 * spare entry starting with next_luid.
6868 */
6869 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6870 listener->conf.id.key = listener->luid = next_id;
6871 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006872 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006873 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006874
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006875 /* enable separate counters */
6876 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6877 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006878 if (!listener->name)
6879 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006880 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006881
Willy Tarreaue6b98942007-10-29 01:09:36 +01006882 if (curproxy->options & PR_O_TCP_NOLING)
6883 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006884 if (!listener->maxconn)
6885 listener->maxconn = curproxy->maxconn;
6886 if (!listener->backlog)
6887 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006888 if (!listener->maxaccept)
6889 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6890
6891 /* we want to have an optimal behaviour on single process mode to
6892 * maximize the work at once, but in multi-process we want to keep
6893 * some fairness between processes, so we target half of the max
6894 * number of events to be balanced over all the processes the proxy
6895 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6896 * used to disable the limit.
6897 */
6898 if (listener->maxaccept > 0) {
6899 if (nbproc > 1)
6900 listener->maxaccept = (listener->maxaccept + 1) / 2;
6901 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6902 }
6903
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006904 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006905 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006906 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006907 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006908
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006909 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6910 listener->options |= LI_O_TCP_RULES;
6911
Willy Tarreaude3041d2010-05-31 10:56:17 +02006912 if (curproxy->mon_mask.s_addr)
6913 listener->options |= LI_O_CHK_MONNET;
6914
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006915 /* smart accept mode is automatic in HTTP mode */
6916 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006917 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006918 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6919 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006920 }
6921
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006922 /* Release unused SSL configs */
6923 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6924 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006925 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006926#ifdef USE_OPENSSL
6927 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006928 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006929 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006930 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006931 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006932#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006933 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006934
Willy Tarreau102df612014-05-07 23:56:38 +02006935 if (nbproc > 1) {
6936 if (curproxy->uri_auth) {
6937 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6938 curproxy->id);
6939 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6940 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6941 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006942 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006943 }
Willy Tarreau102df612014-05-07 23:56:38 +02006944 if (curproxy->appsession_name) {
6945 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6946 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006947 }
Willy Tarreau102df612014-05-07 23:56:38 +02006948 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6949 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6950 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006951 }
6952 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006953
6954 /* create the task associated with the proxy */
6955 curproxy->task = task_new();
6956 if (curproxy->task) {
6957 curproxy->task->context = curproxy;
6958 curproxy->task->process = manage_proxy;
6959 /* no need to queue, it will be done automatically if some
6960 * listener gets limited.
6961 */
6962 curproxy->task->expire = TICK_ETERNITY;
6963 } else {
6964 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6965 curproxy->id);
6966 cfgerr++;
6967 }
6968
Willy Tarreaubaaee002006-06-26 02:48:02 +02006969 curproxy = curproxy->next;
6970 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006971
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006972 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02006973 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02006974 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
6975 unsigned long mask;
6976
6977 mask = nbits(global.nbproc);
6978 if (global.stats_fe->bind_proc)
6979 mask &= global.stats_fe->bind_proc;
6980
6981 if (bind_conf->bind_proc)
6982 mask &= bind_conf->bind_proc;
6983
6984 /* stop here if more than one process is used */
6985 if (popcount(mask) > 1)
6986 break;
6987 }
6988 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
6989 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 +01006990 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006991 }
6992
6993 /* automatically compute fullconn if not set. We must not do it in the
6994 * loop above because cross-references are not yet fully resolved.
6995 */
6996 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6997 /* If <fullconn> is not set, let's set it to 10% of the sum of
6998 * the possible incoming frontend's maxconns.
6999 */
7000 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7001 struct proxy *fe;
7002 int total = 0;
7003
7004 /* sum up the number of maxconns of frontends which
7005 * reference this backend at least once or which are
7006 * the same one ('listen').
7007 */
7008 for (fe = proxy; fe; fe = fe->next) {
7009 struct switching_rule *rule;
7010 struct hdr_exp *exp;
7011 int found = 0;
7012
7013 if (!(fe->cap & PR_CAP_FE))
7014 continue;
7015
7016 if (fe == curproxy) /* we're on a "listen" instance */
7017 found = 1;
7018
7019 if (fe->defbe.be == curproxy) /* "default_backend" */
7020 found = 1;
7021
7022 /* check if a "use_backend" rule matches */
7023 if (!found) {
7024 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007025 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007026 found = 1;
7027 break;
7028 }
7029 }
7030 }
7031
7032 /* check if a "reqsetbe" rule matches */
7033 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7034 if (exp->action == ACT_SETBE &&
7035 (struct proxy *)exp->replace == curproxy) {
7036 found = 1;
7037 break;
7038 }
7039 }
7040
7041 /* now we've checked all possible ways to reference a backend
7042 * from a frontend.
7043 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007044 if (!found)
7045 continue;
7046 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007047 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007048 /* we have the sum of the maxconns in <total>. We only
7049 * keep 10% of that sum to set the default fullconn, with
7050 * a hard minimum of 1 (to avoid a divide by zero).
7051 */
7052 curproxy->fullconn = (total + 9) / 10;
7053 if (!curproxy->fullconn)
7054 curproxy->fullconn = 1;
7055 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007056 }
7057
Willy Tarreau056f5682010-06-06 15:51:11 +02007058 /* initialize stick-tables on backend capable proxies. This must not
7059 * be done earlier because the data size may be discovered while parsing
7060 * other proxies.
7061 */
Godbach9703e662013-12-11 21:11:41 +08007062 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007063 if (curproxy->state == PR_STSTOPPED)
7064 continue;
7065
Godbach9703e662013-12-11 21:11:41 +08007066 if (!stktable_init(&curproxy->table)) {
7067 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7068 cfgerr++;
7069 }
7070 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007071
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007072 /*
7073 * Recount currently required checks.
7074 */
7075
7076 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7077 int optnum;
7078
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007079 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7080 if (curproxy->options & cfg_opts[optnum].val)
7081 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007082
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007083 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7084 if (curproxy->options2 & cfg_opts2[optnum].val)
7085 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007086 }
7087
Willy Tarreau122541c2011-09-07 21:24:49 +02007088 if (peers) {
7089 struct peers *curpeers = peers, **last;
7090 struct peer *p, *pb;
7091
7092 /* Remove all peers sections which don't have a valid listener.
7093 * This can happen when a peers section is never referenced and
7094 * does not contain a local peer.
7095 */
7096 last = &peers;
7097 while (*last) {
7098 curpeers = *last;
7099 if (curpeers->peers_fe) {
7100 last = &curpeers->next;
7101 continue;
7102 }
7103
7104 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7105 curpeers->id, localpeer);
7106
7107 p = curpeers->remote;
7108 while (p) {
7109 pb = p->next;
7110 free(p->id);
7111 free(p);
7112 p = pb;
7113 }
7114
7115 /* Destroy and unlink this curpeers section.
7116 * Note: curpeers is backed up into *last.
7117 */
7118 free(curpeers->id);
7119 curpeers = curpeers->next;
7120 free(*last);
7121 *last = curpeers;
7122 }
7123 }
7124
Willy Tarreau34eb6712011-10-24 18:15:04 +02007125 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007126 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007127 MEM_F_SHARED);
7128
Willy Tarreaubb925012009-07-23 13:36:36 +02007129 if (cfgerr > 0)
7130 err_code |= ERR_ALERT | ERR_FATAL;
7131 out:
7132 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007133}
7134
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007135/*
7136 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7137 * parsing sessions.
7138 */
7139void cfg_register_keywords(struct cfg_kw_list *kwl)
7140{
7141 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7142}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007144/*
7145 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7146 */
7147void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7148{
7149 LIST_DEL(&kwl->list);
7150 LIST_INIT(&kwl->list);
7151}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007152
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007153/* this function register new section in the haproxy configuration file.
7154 * <section_name> is the name of this new section and <section_parser>
7155 * is the called parser. If two section declaration have the same name,
7156 * only the first declared is used.
7157 */
7158int cfg_register_section(char *section_name,
7159 int (*section_parser)(const char *, int, char **, int))
7160{
7161 struct cfg_section *cs;
7162
7163 cs = calloc(1, sizeof(*cs));
7164 if (!cs) {
7165 Alert("register section '%s': out of memory.\n", section_name);
7166 return 0;
7167 }
7168
7169 cs->section_name = section_name;
7170 cs->section_parser = section_parser;
7171
7172 LIST_ADDQ(&sections, &cs->list);
7173
7174 return 1;
7175}
7176
Willy Tarreaubaaee002006-06-26 02:48:02 +02007177/*
7178 * Local variables:
7179 * c-indent-level: 8
7180 * c-basic-offset: 8
7181 * End:
7182 */