blob: 23e2bdd18826f401ede422d99342c7e265ee4744 [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
1508static int create_cond_regex_rule(const char *file, int line,
1509 struct proxy *px, int dir, int action, int flags,
1510 const char *cmd, const char *reg, const char *repl,
1511 const char **cond_start)
1512{
1513 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001514 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001515 const char *err;
1516 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001517 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001518
1519 if (px == &defproxy) {
1520 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto err;
1523 }
1524
1525 if (*reg == 0) {
1526 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1527 err_code |= ERR_ALERT | ERR_FATAL;
1528 goto err;
1529 }
1530
1531 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1532 err_code |= ERR_WARN;
1533
Willy Tarreau5321c422010-01-28 20:35:13 +01001534 if (cond_start &&
1535 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001536 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1537 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1538 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto err;
1541 }
1542 }
1543 else if (cond_start && **cond_start) {
1544 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1545 file, line, cmd, *cond_start);
1546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto err;
1548 }
1549
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001550 err_code |= warnif_cond_conflicts(cond,
1551 (dir == SMP_OPT_DIR_REQ) ?
1552 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1553 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1554 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001555
Willy Tarreauade5ec42010-01-28 19:33:49 +01001556 preg = calloc(1, sizeof(regex_t));
1557 if (!preg) {
1558 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1559 err_code = ERR_ALERT | ERR_FATAL;
1560 goto err;
1561 }
1562
1563 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1564 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1565 err_code = ERR_ALERT | ERR_FATAL;
1566 goto err;
1567 }
1568
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001569 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001570 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001571 if (repl && err) {
1572 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1573 file, line, cmd, *err);
1574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto err;
1576 }
1577
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001578 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001579 err_code |= ERR_WARN;
1580
Willy Tarreauf4068b62012-05-08 17:37:49 +02001581 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001582 return err_code;
1583 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001584 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001585 free(preg);
1586 return err_code;
1587}
1588
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001591 * Returns the error code, 0 if OK, or any combination of :
1592 * - ERR_ABORT: must abort ASAP
1593 * - ERR_FATAL: we can continue parsing but not start the service
1594 * - ERR_WARN: a warning has been emitted
1595 * - ERR_ALERT: an alert has been emitted
1596 * Only the two first ones can stop processing, the two others are just
1597 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001599int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1600{
1601 static struct peers *curpeers = NULL;
1602 struct peer *newpeer = NULL;
1603 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001604 struct bind_conf *bind_conf;
1605 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001606 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001607 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001608
1609 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001610 if (!*args[1]) {
1611 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001612 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001613 goto out;
1614 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001615
1616 err = invalid_char(args[1]);
1617 if (err) {
1618 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1619 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001620 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001621 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001622 }
1623
1624 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1625 /*
1626 * If there are two proxies with the same name only following
1627 * combinations are allowed:
1628 */
1629 if (strcmp(curpeers->id, args[1]) == 0) {
1630 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1631 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1632 err_code |= ERR_WARN;
1633 }
1634 }
1635
1636 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1637 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1638 err_code |= ERR_ALERT | ERR_ABORT;
1639 goto out;
1640 }
1641
1642 curpeers->next = peers;
1643 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001644 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001645 curpeers->conf.line = linenum;
1646 curpeers->last_change = now.tv_sec;
1647 curpeers->id = strdup(args[1]);
1648 }
1649 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001650 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001651 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001652 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001653
1654 if (!*args[2]) {
1655 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1656 file, linenum, args[0]);
1657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
1660
1661 err = invalid_char(args[1]);
1662 if (err) {
1663 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1664 file, linenum, *err, args[1]);
1665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
1667 }
1668
1669 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1670 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1671 err_code |= ERR_ALERT | ERR_ABORT;
1672 goto out;
1673 }
1674
1675 /* the peers are linked backwards first */
1676 curpeers->count++;
1677 newpeer->next = curpeers->remote;
1678 curpeers->remote = newpeer;
1679 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001680 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001681 newpeer->conf.line = linenum;
1682
1683 newpeer->last_change = now.tv_sec;
1684 newpeer->id = strdup(args[1]);
1685
Willy Tarreau902636f2013-03-10 19:44:48 +01001686 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001687 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001688 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001691 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001692
1693 proto = protocol_by_family(sk->ss_family);
1694 if (!proto || !proto->connect) {
1695 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1696 file, linenum, args[0], args[1]);
1697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
1699 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001700
1701 if (port1 != port2) {
1702 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1703 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707
Willy Tarreau2aa38802013-02-20 19:20:59 +01001708 if (!port1) {
1709 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1710 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
1713 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001714
Emeric Brun32da3c42010-09-23 18:39:19 +02001715 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001716 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001717 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001718 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001719
Emeric Brun32da3c42010-09-23 18:39:19 +02001720 if (strcmp(newpeer->id, localpeer) == 0) {
1721 /* Current is local peer, it define a frontend */
1722 newpeer->local = 1;
1723
1724 if (!curpeers->peers_fe) {
1725 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1726 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1727 err_code |= ERR_ALERT | ERR_ABORT;
1728 goto out;
1729 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001730
Willy Tarreau237250c2011-07-29 01:49:03 +02001731 init_new_proxy(curpeers->peers_fe);
1732 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001733
1734 curpeers->peers_fe->last_change = now.tv_sec;
1735 curpeers->peers_fe->id = strdup(args[1]);
1736 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001737 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001738 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1739 curpeers->peers_fe->timeout.connect = 5000;
1740 curpeers->peers_fe->accept = peer_accept;
1741 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001742 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1743 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001744
1745 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1746
Willy Tarreau902636f2013-03-10 19:44:48 +01001747 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1748 if (errmsg && *errmsg) {
1749 indent_msg(&errmsg, 2);
1750 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001751 }
1752 else
1753 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1754 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001755 err_code |= ERR_FATAL;
1756 goto out;
1757 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001758
1759 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1760 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1761 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1762 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1763 l->accept = session_accept;
1764 l->handler = process_session;
1765 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1766 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1767 global.maxsock += l->maxconn;
1768 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001769 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001770 else {
1771 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1772 file, linenum, args[0], args[1],
1773 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1774 err_code |= ERR_FATAL;
1775 goto out;
1776 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001777 }
1778 } /* neither "peer" nor "peers" */
1779 else if (*args[0] != 0) {
1780 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001786 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001787 return err_code;
1788}
1789
Willy Tarreau3842f002009-06-14 11:39:52 +02001790int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791{
1792 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001793 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001794 int rc;
1795 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001796 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001797 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001798 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001799 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001800 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 if (!strcmp(args[0], "listen"))
1803 rc = PR_CAP_LISTEN;
1804 else if (!strcmp(args[0], "frontend"))
1805 rc = PR_CAP_FE | PR_CAP_RS;
1806 else if (!strcmp(args[0], "backend"))
1807 rc = PR_CAP_BE | PR_CAP_RS;
1808 else if (!strcmp(args[0], "ruleset"))
1809 rc = PR_CAP_RS;
1810 else
1811 rc = PR_CAP_NONE;
1812
1813 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001814 struct ebpt_node *node;
1815
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 if (!*args[1]) {
1817 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1818 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1819 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001820 err_code |= ERR_ALERT | ERR_ABORT;
1821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001823
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001824 err = invalid_char(args[1]);
1825 if (err) {
1826 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1827 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001828 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001829 }
1830
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001831 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1832 curproxy = container_of(node, struct proxy, conf.by_name);
1833
1834 if (strcmp(curproxy->id, args[1]) != 0)
1835 break;
1836
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001837 /*
1838 * If there are two proxies with the same name only following
1839 * combinations are allowed:
1840 *
1841 * listen backend frontend ruleset
1842 * listen - - - -
1843 * backend - - OK -
1844 * frontend - OK - -
1845 * ruleset - - - -
1846 */
1847
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001848 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1849 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001850 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1851 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1852 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001853 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001854 }
1855 }
1856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1858 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001859 err_code |= ERR_ALERT | ERR_ABORT;
1860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001862
Willy Tarreau97cb7802010-01-03 20:23:58 +01001863 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 curproxy->next = proxy;
1865 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001866 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1867 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001868 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001870 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001871 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872
1873 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001874 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001875 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001876
Willy Tarreau4348fad2012-09-20 16:48:07 +02001877 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1878
Willy Tarreau902636f2013-03-10 19:44:48 +01001879 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1880 if (errmsg && *errmsg) {
1881 indent_msg(&errmsg, 2);
1882 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001883 }
1884 else
1885 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1886 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_FATAL;
1888 goto out;
1889 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001890
Willy Tarreau4348fad2012-09-20 16:48:07 +02001891 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001892 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
1895
1896 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001897 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001898 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001899
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001902 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001903 curproxy->no_options = defproxy.no_options;
1904 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001905 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001906 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001907 curproxy->except_net = defproxy.except_net;
1908 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001909 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001910 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001912 if (defproxy.fwdfor_hdr_len) {
1913 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1914 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1915 }
1916
Willy Tarreaub86db342009-11-30 11:50:16 +01001917 if (defproxy.orgto_hdr_len) {
1918 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1919 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1920 }
1921
Mark Lamourinec2247f02012-01-04 13:02:01 -05001922 if (defproxy.server_id_hdr_len) {
1923 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1924 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1925 }
1926
Willy Tarreau977b8e42006-12-29 14:19:17 +01001927 if (curproxy->cap & PR_CAP_FE) {
1928 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001929 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001930 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001931
1932 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001933 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1934 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935
1936 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939 if (curproxy->cap & PR_CAP_BE) {
1940 curproxy->fullconn = defproxy.fullconn;
1941 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001942 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001944 if (defproxy.check_req) {
1945 curproxy->check_req = calloc(1, defproxy.check_len);
1946 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1947 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001948 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001950 if (defproxy.expect_str) {
1951 curproxy->expect_str = strdup(defproxy.expect_str);
1952 if (defproxy.expect_regex) {
1953 /* note: this regex is known to be valid */
1954 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1955 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1956 }
1957 }
1958
Willy Tarreau67402132012-05-31 20:40:20 +02001959 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001960 if (defproxy.cookie_name)
1961 curproxy->cookie_name = strdup(defproxy.cookie_name);
1962 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001963 if (defproxy.cookie_domain)
1964 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001965
Willy Tarreau31936852010-10-06 16:59:56 +02001966 if (defproxy.cookie_maxidle)
1967 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1968
1969 if (defproxy.cookie_maxlife)
1970 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1971
Emeric Brun647caf12009-06-30 17:57:00 +02001972 if (defproxy.rdp_cookie_name)
1973 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1974 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1975
Willy Tarreau01732802007-11-01 22:48:15 +01001976 if (defproxy.url_param_name)
1977 curproxy->url_param_name = strdup(defproxy.url_param_name);
1978 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001979
Benoitaffb4812009-03-25 13:02:10 +01001980 if (defproxy.hh_name)
1981 curproxy->hh_name = strdup(defproxy.hh_name);
1982 curproxy->hh_len = defproxy.hh_len;
1983 curproxy->hh_match_domain = defproxy.hh_match_domain;
1984
Willy Tarreauef9a3602012-12-08 22:29:20 +01001985 if (defproxy.conn_src.iface_name)
1986 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1987 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001988 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001989#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001990 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001991#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001994 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001995 if (defproxy.capture_name)
1996 curproxy->capture_name = strdup(defproxy.capture_name);
1997 curproxy->capture_namelen = defproxy.capture_namelen;
1998 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000
Willy Tarreau977b8e42006-12-29 14:19:17 +01002001 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002002 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002003 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002004 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002005 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002006 curproxy->mon_net = defproxy.mon_net;
2007 curproxy->mon_mask = defproxy.mon_mask;
2008 if (defproxy.monitor_uri)
2009 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2010 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002011 if (defproxy.defbe.name)
2012 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002013
2014 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002015 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2016 if (curproxy->conf.logformat_string &&
2017 curproxy->conf.logformat_string != default_http_log_format &&
2018 curproxy->conf.logformat_string != default_tcp_log_format &&
2019 curproxy->conf.logformat_string != clf_http_log_format)
2020 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2021
2022 if (defproxy.conf.lfs_file) {
2023 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2024 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2025 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002026 }
2027
2028 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002029 curproxy->timeout.connect = defproxy.timeout.connect;
2030 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002031 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002032 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002033 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002034 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002035 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002036 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002037 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038 }
2039
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002041 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002042
2043 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002044 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002045 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002046 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002047 LIST_INIT(&node->list);
2048 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2049 }
2050
Willy Tarreau62a61232013-04-12 18:13:46 +02002051 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2052 if (curproxy->conf.uniqueid_format_string)
2053 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2054
2055 if (defproxy.conf.uif_file) {
2056 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2057 curproxy->conf.uif_line = defproxy.conf.uif_line;
2058 }
William Lallemanda73203e2012-03-12 12:48:57 +01002059
2060 /* copy default header unique id */
2061 if (defproxy.header_unique_id)
2062 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2063
William Lallemand82fe75c2012-10-23 10:25:10 +02002064 /* default compression options */
2065 if (defproxy.comp != NULL) {
2066 curproxy->comp = calloc(1, sizeof(struct comp));
2067 curproxy->comp->algos = defproxy.comp->algos;
2068 curproxy->comp->types = defproxy.comp->types;
2069 }
2070
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002072 curproxy->conf.used_listener_id = EB_ROOT;
2073 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002074
Willy Tarreau93893792009-07-23 13:19:11 +02002075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 }
2077 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2078 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002079 /* FIXME-20070101: we should do this too at the end of the
2080 * config parsing to free all default values.
2081 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002082 free(defproxy.check_req);
2083 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002084 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002085 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002086 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002087 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002088 free(defproxy.capture_name);
2089 free(defproxy.monitor_uri);
2090 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002091 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002092 free(defproxy.fwdfor_hdr_name);
2093 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002094 free(defproxy.orgto_hdr_name);
2095 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002096 free(defproxy.server_id_hdr_name);
2097 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002098 free(defproxy.expect_str);
2099 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002100
Willy Tarreau62a61232013-04-12 18:13:46 +02002101 if (defproxy.conf.logformat_string != default_http_log_format &&
2102 defproxy.conf.logformat_string != default_tcp_log_format &&
2103 defproxy.conf.logformat_string != clf_http_log_format)
2104 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002105
Willy Tarreau62a61232013-04-12 18:13:46 +02002106 free(defproxy.conf.uniqueid_format_string);
2107 free(defproxy.conf.lfs_file);
2108 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002109
Willy Tarreaua534fea2008-08-03 12:19:50 +02002110 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002111 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002112
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113 /* we cannot free uri_auth because it might already be used */
2114 init_default_instance();
2115 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002116 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2117 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002118 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 }
2121 else if (curproxy == NULL) {
2122 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_FATAL;
2124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002126
2127 /* update the current file and line being parsed */
2128 curproxy->conf.args.file = curproxy->conf.file;
2129 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002130
2131 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002132 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2133 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2134 if (err_code & ERR_FATAL)
2135 goto out;
2136 }
2137 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002138 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002139 int cur_arg;
2140
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 if (curproxy == &defproxy) {
2142 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002146 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002147 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148
Willy Tarreau24709282013-03-10 21:32:12 +01002149 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002150 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002155
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002156 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002157
2158 /* use default settings for unix sockets */
2159 bind_conf->ux.uid = global.unix_bind.ux.uid;
2160 bind_conf->ux.gid = global.unix_bind.ux.gid;
2161 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002162
2163 /* NOTE: the following line might create several listeners if there
2164 * are comma-separated IPs or port ranges. So all further processing
2165 * will have to be applied to all listeners created after last_listen.
2166 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002167 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2168 if (errmsg && *errmsg) {
2169 indent_msg(&errmsg, 2);
2170 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002171 }
2172 else
2173 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2174 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002178
Willy Tarreau4348fad2012-09-20 16:48:07 +02002179 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2180 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002181 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002182 }
2183
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002184 cur_arg = 2;
2185 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002186 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002187 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002188 char *err;
2189
Willy Tarreau26982662012-09-12 23:17:10 +02002190 kw = bind_find_kw(args[cur_arg]);
2191 if (kw) {
2192 char *err = NULL;
2193 int code;
2194
2195 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002196 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2197 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002198 cur_arg += 1 + kw->skip ;
2199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
2202
Willy Tarreau4348fad2012-09-20 16:48:07 +02002203 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002204 err_code |= code;
2205
2206 if (code) {
2207 if (err && *err) {
2208 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002209 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002210 }
2211 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002212 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2213 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002214 if (code & ERR_FATAL) {
2215 free(err);
2216 cur_arg += 1 + kw->skip;
2217 goto out;
2218 }
2219 }
2220 free(err);
2221 cur_arg += 1 + kw->skip;
2222 continue;
2223 }
2224
Willy Tarreau8638f482012-09-18 18:01:17 +02002225 err = NULL;
2226 if (!bind_dumped) {
2227 bind_dump_kws(&err);
2228 indent_msg(&err, 4);
2229 bind_dumped = 1;
2230 }
2231
2232 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2233 file, linenum, args[0], args[1], args[cur_arg],
2234 err ? " Registered keywords :" : "", err ? err : "");
2235 free(err);
2236
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002239 }
Willy Tarreau93893792009-07-23 13:19:11 +02002240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 }
2242 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002243 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002249 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002251
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 /* flush useless bits */
2253 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002256 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002257 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002259
Willy Tarreau1c47f852006-07-09 08:22:27 +02002260 if (!*args[1]) {
2261 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002265 }
2266
Willy Tarreaua534fea2008-08-03 12:19:50 +02002267 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002268 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002269 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002270 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002271 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2272
Willy Tarreau93893792009-07-23 13:19:11 +02002273 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2276 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2277 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2278 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2279 else {
2280 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 }
2284 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002285 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002286 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002287
2288 if (curproxy == &defproxy) {
2289 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2290 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002293 }
2294
2295 if (!*args[1]) {
2296 Alert("parsing [%s:%d]: '%s' expects an integer argument.\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 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002303 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002304
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002305 if (curproxy->uuid <= 0) {
2306 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002307 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002310 }
2311
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002312 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2313 if (node) {
2314 struct proxy *target = container_of(node, struct proxy, conf.id);
2315 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2316 file, linenum, proxy_type_str(curproxy), curproxy->id,
2317 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002322 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002323 else if (!strcmp(args[0], "description")) {
2324 int i, len=0;
2325 char *d;
2326
Cyril Bonté99ed3272010-01-24 23:29:44 +01002327 if (curproxy == &defproxy) {
2328 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2329 file, linenum, args[0]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002334 if (!*args[1]) {
2335 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2336 file, linenum, args[0]);
2337 return -1;
2338 }
2339
Willy Tarreau348acfe2014-04-14 15:00:39 +02002340 for (i = 1; *args[i]; i++)
2341 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002342
2343 d = (char *)calloc(1, len);
2344 curproxy->desc = d;
2345
Willy Tarreau348acfe2014-04-14 15:00:39 +02002346 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2347 for (i = 2; *args[i]; i++)
2348 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002349
2350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2352 curproxy->state = PR_STSTOPPED;
2353 }
2354 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2355 curproxy->state = PR_STNEW;
2356 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002357 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2358 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002359 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002360
2361 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002362 unsigned int low, high;
2363
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002364 if (strcmp(args[cur_arg], "all") == 0) {
2365 set = 0;
2366 break;
2367 }
2368 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002369 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002370 }
2371 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002372 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002373 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002374 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002375 char *dash = strchr(args[cur_arg], '-');
2376
2377 low = high = str2uic(args[cur_arg]);
2378 if (dash)
2379 high = str2uic(dash + 1);
2380
2381 if (high < low) {
2382 unsigned int swap = low;
2383 low = high;
2384 high = swap;
2385 }
2386
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002387 if (low < 1 || high > LONGBITS) {
2388 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2389 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002392 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002393 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002394 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002395 }
2396 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002397 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2398 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002401 }
2402 cur_arg++;
2403 }
2404 curproxy->bind_proc = set;
2405 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002406 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002407 if (curproxy == &defproxy) {
2408 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002411 }
2412
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002413 err = invalid_char(args[1]);
2414 if (err) {
2415 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2416 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002418 }
2419
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002420 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002421 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2422 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002425 }
2426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2428 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002432
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 if (*(args[1]) == 0) {
2434 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2435 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002439
Willy Tarreau67402132012-05-31 20:40:20 +02002440 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002441 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002442 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002443 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 curproxy->cookie_name = strdup(args[1]);
2445 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002446
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 cur_arg = 2;
2448 while (*(args[cur_arg])) {
2449 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002450 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
2452 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002453 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
2455 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002456 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
2458 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002459 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 }
2461 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002462 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002464 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002465 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002468 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002470 else if (!strcmp(args[cur_arg], "httponly")) {
2471 curproxy->ck_opts |= PR_CK_HTTPONLY;
2472 }
2473 else if (!strcmp(args[cur_arg], "secure")) {
2474 curproxy->ck_opts |= PR_CK_SECURE;
2475 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002476 else if (!strcmp(args[cur_arg], "domain")) {
2477 if (!*args[cur_arg + 1]) {
2478 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2479 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002482 }
2483
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002484 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002485 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002486 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2487 " dots nor does not start with a dot."
2488 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002489 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002490 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002491 }
2492
2493 err = invalid_domainchar(args[cur_arg + 1]);
2494 if (err) {
2495 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2496 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002499 }
2500
Willy Tarreau68a897b2009-12-03 23:28:34 +01002501 if (!curproxy->cookie_domain) {
2502 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2503 } else {
2504 /* one domain was already specified, add another one by
2505 * building the string which will be returned along with
2506 * the cookie.
2507 */
2508 char *new_ptr;
2509 int new_len = strlen(curproxy->cookie_domain) +
2510 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2511 new_ptr = malloc(new_len);
2512 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2513 free(curproxy->cookie_domain);
2514 curproxy->cookie_domain = new_ptr;
2515 }
Willy Tarreau31936852010-10-06 16:59:56 +02002516 cur_arg++;
2517 }
2518 else if (!strcmp(args[cur_arg], "maxidle")) {
2519 unsigned int maxidle;
2520 const char *res;
2521
2522 if (!*args[cur_arg + 1]) {
2523 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2524 file, linenum, args[cur_arg]);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528
2529 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2530 if (res) {
2531 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2532 file, linenum, *res, args[cur_arg]);
2533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
2535 }
2536 curproxy->cookie_maxidle = maxidle;
2537 cur_arg++;
2538 }
2539 else if (!strcmp(args[cur_arg], "maxlife")) {
2540 unsigned int maxlife;
2541 const char *res;
2542
2543 if (!*args[cur_arg + 1]) {
2544 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2545 file, linenum, args[cur_arg]);
2546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
2548 }
2549
2550 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2551 if (res) {
2552 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2553 file, linenum, *res, args[cur_arg]);
2554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
2556 }
2557 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002558 cur_arg++;
2559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002561 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 +02002562 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
2566 cur_arg++;
2567 }
Willy Tarreau67402132012-05-31 20:40:20 +02002568 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2570 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
2573
Willy Tarreau67402132012-05-31 20:40:20 +02002574 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2576 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002579
Willy Tarreau67402132012-05-31 20:40:20 +02002580 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002581 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2582 file, linenum);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002586 else if (!strcmp(args[0], "persist")) { /* persist */
2587 if (*(args[1]) == 0) {
2588 Alert("parsing [%s:%d] : missing persist method.\n",
2589 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002592 }
2593
2594 if (!strncmp(args[1], "rdp-cookie", 10)) {
2595 curproxy->options2 |= PR_O2_RDPC_PRST;
2596
Emeric Brunb982a3d2010-01-04 15:45:53 +01002597 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002598 const char *beg, *end;
2599
2600 beg = args[1] + 11;
2601 end = strchr(beg, ')');
2602
2603 if (!end || end == beg) {
2604 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2605 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002608 }
2609
2610 free(curproxy->rdp_cookie_name);
2611 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2612 curproxy->rdp_cookie_len = end-beg;
2613 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002614 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002615 free(curproxy->rdp_cookie_name);
2616 curproxy->rdp_cookie_name = strdup("msts");
2617 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2618 }
2619 else { /* syntax */
2620 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2621 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002624 }
2625 }
2626 else {
2627 Alert("parsing [%s:%d] : unknown persist method.\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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002634 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002636 if (curproxy == &defproxy) {
2637 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
2641
Willy Tarreau977b8e42006-12-29 14:19:17 +01002642 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002644
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002646 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 }
2651 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002652 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 curproxy->appsession_name = strdup(args[1]);
2654 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2655 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002656 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2657 if (err) {
2658 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2659 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002662 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002663 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002664
Willy Tarreau51041c72007-09-09 21:56:53 +02002665 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2666 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_ABORT;
2668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002670
2671 cur_arg = 6;
2672 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002673 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2674 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002675 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002676 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002677 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002678 } else if (!strcmp(args[cur_arg], "prefix")) {
2679 curproxy->options2 |= PR_O2_AS_PFX;
2680 } else if (!strcmp(args[cur_arg], "mode")) {
2681 if (!*args[cur_arg + 1]) {
2682 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2683 file, linenum, args[0], args[cur_arg]);
2684 err_code |= ERR_ALERT | ERR_FATAL;
2685 goto out;
2686 }
2687
2688 cur_arg++;
2689 if (!strcmp(args[cur_arg], "query-string")) {
2690 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2691 curproxy->options2 |= PR_O2_AS_M_QS;
2692 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2693 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2694 curproxy->options2 |= PR_O2_AS_M_PP;
2695 } else {
2696 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002701 cur_arg++;
2702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 } /* Url App Session */
2704 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002705 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002707
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002709 if (curproxy == &defproxy) {
2710 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 if (*(args[4]) == 0) {
2716 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2717 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002721 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 curproxy->capture_name = strdup(args[2]);
2723 curproxy->capture_namelen = strlen(curproxy->capture_name);
2724 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 curproxy->to_log |= LW_COOKIE;
2726 }
2727 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2728 struct cap_hdr *hdr;
2729
2730 if (curproxy == &defproxy) {
2731 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 +02002732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 }
2735
2736 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2737 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2738 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 hdr = calloc(sizeof(struct cap_hdr), 1);
2744 hdr->next = curproxy->req_cap;
2745 hdr->name = strdup(args[3]);
2746 hdr->namelen = strlen(args[3]);
2747 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002748 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 hdr->index = curproxy->nb_req_cap++;
2750 curproxy->req_cap = hdr;
2751 curproxy->to_log |= LW_REQHDR;
2752 }
2753 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2754 struct cap_hdr *hdr;
2755
2756 if (curproxy == &defproxy) {
2757 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 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
2761
2762 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2763 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2764 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 hdr = calloc(sizeof(struct cap_hdr), 1);
2769 hdr->next = curproxy->rsp_cap;
2770 hdr->name = strdup(args[3]);
2771 hdr->namelen = strlen(args[3]);
2772 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002773 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 hdr->index = curproxy->nb_rsp_cap++;
2775 curproxy->rsp_cap = hdr;
2776 curproxy->to_log |= LW_RSPHDR;
2777 }
2778 else {
2779 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2780 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
2784 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002788
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 if (*(args[1]) == 0) {
2790 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2791 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 }
2795 curproxy->conn_retries = atol(args[1]);
2796 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002797 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002798 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002799
2800 if (curproxy == &defproxy) {
2801 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804 }
2805
Willy Tarreau20b0de52012-12-24 15:45:22 +01002806 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2807 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2808 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2809 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002810 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002811 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2812 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 +01002813 file, linenum, args[0]);
2814 err_code |= ERR_WARN;
2815 }
2816
Willy Tarreauff011f22011-01-06 17:51:27 +01002817 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002818
Willy Tarreauff011f22011-01-06 17:51:27 +01002819 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002820 err_code |= ERR_ALERT | ERR_ABORT;
2821 goto out;
2822 }
2823
Willy Tarreau5002f572014-04-23 01:32:02 +02002824 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002825 err_code |= warnif_cond_conflicts(rule->cond,
2826 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2827 file, linenum);
2828
Willy Tarreauff011f22011-01-06 17:51:27 +01002829 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002830 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002831 else if (!strcmp(args[0], "http-response")) { /* response access control */
2832 struct http_res_rule *rule;
2833
2834 if (curproxy == &defproxy) {
2835 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839
2840 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2841 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2842 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2843 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2844 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2845 file, linenum, args[0]);
2846 err_code |= ERR_WARN;
2847 }
2848
2849 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2850
2851 if (!rule) {
2852 err_code |= ERR_ALERT | ERR_ABORT;
2853 goto out;
2854 }
2855
2856 err_code |= warnif_cond_conflicts(rule->cond,
2857 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2858 file, linenum);
2859
2860 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2861 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002862 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2863 /* set the header name and length into the proxy structure */
2864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2865 err_code |= ERR_WARN;
2866
2867 if (!*args[1]) {
2868 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2869 file, linenum, args[0]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873
2874 /* set the desired header name */
2875 free(curproxy->server_id_hdr_name);
2876 curproxy->server_id_hdr_name = strdup(args[1]);
2877 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2878 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002879 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002880 struct http_req_rule *rule;
2881
Willy Tarreaub099aca2008-10-12 17:26:37 +02002882 if (curproxy == &defproxy) {
2883 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002886 }
2887
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002888 /* emulate "block" using "http-request block". Since these rules are supposed to
2889 * be processed before all http-request rules, we put them into their own list
2890 * and will insert them at the end.
2891 */
2892 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2893 if (!rule) {
2894 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002895 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002896 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002897 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2898 err_code |= warnif_cond_conflicts(rule->cond,
2899 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2900 file, linenum);
2901 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002902
2903 if (!already_warned(WARN_BLOCK_DEPRECATED))
2904 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]);
2905
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002906 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002907 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002908 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002909
Cyril Bonté99ed3272010-01-24 23:29:44 +01002910 if (curproxy == &defproxy) {
2911 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002916 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002917 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2918 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002921 }
2922
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002923 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002924 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002925 err_code |= warnif_cond_conflicts(rule->cond,
2926 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2927 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002928 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002929 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002930 struct switching_rule *rule;
2931
Willy Tarreaub099aca2008-10-12 17:26:37 +02002932 if (curproxy == &defproxy) {
2933 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002936 }
2937
Willy Tarreau55ea7572007-06-17 19:56:27 +02002938 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002940
2941 if (*(args[1]) == 0) {
2942 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002945 }
2946
Willy Tarreauf51658d2014-04-23 01:21:56 +02002947 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2948 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2949 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2950 file, linenum, errmsg);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002954
Willy Tarreauf51658d2014-04-23 01:21:56 +02002955 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002956 }
2957
2958 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2959 rule->cond = cond;
2960 rule->be.name = strdup(args[1]);
2961 LIST_INIT(&rule->list);
2962 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2963 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002964 else if (strcmp(args[0], "use-server") == 0) {
2965 struct server_rule *rule;
2966
2967 if (curproxy == &defproxy) {
2968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972
2973 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2974 err_code |= ERR_WARN;
2975
2976 if (*(args[1]) == 0) {
2977 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981
2982 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2983 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2984 file, linenum, args[0]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002989 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2990 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2991 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002996 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002997
2998 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2999 rule->cond = cond;
3000 rule->srv.name = strdup(args[1]);
3001 LIST_INIT(&rule->list);
3002 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3003 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3004 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003005 else if ((!strcmp(args[0], "force-persist")) ||
3006 (!strcmp(args[0], "ignore-persist"))) {
3007 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003008
3009 if (curproxy == &defproxy) {
3010 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013 }
3014
3015 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3016 err_code |= ERR_WARN;
3017
Willy Tarreauef6494c2010-01-28 17:12:36 +01003018 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003019 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3020 file, linenum, args[0]);
3021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003025 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3026 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3027 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
3030 }
3031
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003032 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3033 * where force-persist is applied.
3034 */
3035 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003036
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003037 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003038 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003039 if (!strcmp(args[0], "force-persist")) {
3040 rule->type = PERSIST_TYPE_FORCE;
3041 } else {
3042 rule->type = PERSIST_TYPE_IGNORE;
3043 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003044 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003045 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003046 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 else if (!strcmp(args[0], "stick-table")) {
3048 int myidx = 1;
3049
Emeric Brun32da3c42010-09-23 18:39:19 +02003050 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003051 curproxy->table.type = (unsigned int)-1;
3052 while (*args[myidx]) {
3053 const char *err;
3054
3055 if (strcmp(args[myidx], "size") == 0) {
3056 myidx++;
3057 if (!*(args[myidx])) {
3058 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3059 file, linenum, args[myidx-1]);
3060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3064 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3065 file, linenum, *err, args[myidx-1]);
3066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
3068 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003069 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003070 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003071 else if (strcmp(args[myidx], "peers") == 0) {
3072 myidx++;
Godbach50523162013-12-11 19:48:57 +08003073 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003074 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3075 file, linenum, args[myidx-1]);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Godbach50523162013-12-11 19:48:57 +08003078 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003079 curproxy->table.peers.name = strdup(args[myidx++]);
3080 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003081 else if (strcmp(args[myidx], "expire") == 0) {
3082 myidx++;
3083 if (!*(args[myidx])) {
3084 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3085 file, linenum, args[myidx-1]);
3086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
3088 }
3089 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3090 if (err) {
3091 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3092 file, linenum, *err, args[myidx-1]);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003097 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003098 }
3099 else if (strcmp(args[myidx], "nopurge") == 0) {
3100 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003101 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003102 }
3103 else if (strcmp(args[myidx], "type") == 0) {
3104 myidx++;
3105 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3106 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3107 file, linenum, args[myidx]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003111 /* myidx already points to next arg */
3112 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003113 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003114 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003115 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003116
3117 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003118 nw = args[myidx];
3119 while (*nw) {
3120 /* the "store" keyword supports a comma-separated list */
3121 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003122 sa = NULL; /* store arg */
3123 while (*nw && *nw != ',') {
3124 if (*nw == '(') {
3125 *nw = 0;
3126 sa = ++nw;
3127 while (*nw != ')') {
3128 if (!*nw) {
3129 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3130 file, linenum, args[0], cw);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134 nw++;
3135 }
3136 *nw = '\0';
3137 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003138 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003139 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003140 if (*nw)
3141 *nw++ = '\0';
3142 type = stktable_get_data_type(cw);
3143 if (type < 0) {
3144 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3145 file, linenum, args[0], cw);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
Willy Tarreauac782882010-06-20 10:41:54 +02003149
3150 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3151 switch (err) {
3152 case PE_NONE: break;
3153 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003154 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3155 file, linenum, args[0], cw);
3156 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003157 break;
3158
3159 case PE_ARG_MISSING:
3160 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3161 file, linenum, args[0], cw);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164
3165 case PE_ARG_NOT_USED:
3166 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3167 file, linenum, args[0], cw);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170
3171 default:
3172 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3173 file, linenum, args[0], cw);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003176 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003177 }
3178 myidx++;
3179 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003180 else {
3181 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3182 file, linenum, args[myidx]);
3183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003185 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003186 }
3187
3188 if (!curproxy->table.size) {
3189 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3190 file, linenum);
3191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
3193 }
3194
3195 if (curproxy->table.type == (unsigned int)-1) {
3196 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3197 file, linenum);
3198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
3200 }
3201 }
3202 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003203 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003204 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003205 int myidx = 0;
3206 const char *name = NULL;
3207 int flags;
3208
3209 if (curproxy == &defproxy) {
3210 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214
3215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3216 err_code |= ERR_WARN;
3217 goto out;
3218 }
3219
3220 myidx++;
3221 if ((strcmp(args[myidx], "store") == 0) ||
3222 (strcmp(args[myidx], "store-request") == 0)) {
3223 myidx++;
3224 flags = STK_IS_STORE;
3225 }
3226 else if (strcmp(args[myidx], "store-response") == 0) {
3227 myidx++;
3228 flags = STK_IS_STORE | STK_ON_RSP;
3229 }
3230 else if (strcmp(args[myidx], "match") == 0) {
3231 myidx++;
3232 flags = STK_IS_MATCH;
3233 }
3234 else if (strcmp(args[myidx], "on") == 0) {
3235 myidx++;
3236 flags = STK_IS_MATCH | STK_IS_STORE;
3237 }
3238 else {
3239 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
3242 }
3243
3244 if (*(args[myidx]) == 0) {
3245 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
3249
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003250 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003251 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003252 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003253 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
3256 }
3257
3258 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003259 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3260 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3261 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003262 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003263 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003264 goto out;
3265 }
3266 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003267 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3268 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3269 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003270 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003271 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003272 goto out;
3273 }
3274 }
3275
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003276 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003277 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003278
Emeric Brunb982a3d2010-01-04 15:45:53 +01003279 if (strcmp(args[myidx], "table") == 0) {
3280 myidx++;
3281 name = args[myidx++];
3282 }
3283
Willy Tarreauef6494c2010-01-28 17:12:36 +01003284 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003285 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3286 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3287 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003288 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003289 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003290 goto out;
3291 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003292 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003293 else if (*(args[myidx])) {
3294 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3295 file, linenum, args[0], args[myidx]);
3296 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003297 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003298 goto out;
3299 }
Emeric Brun97679e72010-09-23 17:56:44 +02003300 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003301 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003302 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003303 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003304
Emeric Brunb982a3d2010-01-04 15:45:53 +01003305 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3306 rule->cond = cond;
3307 rule->expr = expr;
3308 rule->flags = flags;
3309 rule->table.name = name ? strdup(name) : NULL;
3310 LIST_INIT(&rule->list);
3311 if (flags & STK_ON_RSP)
3312 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3313 else
3314 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 else if (!strcmp(args[0], "stats")) {
3317 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3318 curproxy->uri_auth = NULL; /* we must detach from the default config */
3319
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003320 if (!*args[1]) {
3321 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003322 } else if (!strcmp(args[1], "admin")) {
3323 struct stats_admin_rule *rule;
3324
3325 if (curproxy == &defproxy) {
3326 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
3329 }
3330
3331 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3332 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3333 err_code |= ERR_ALERT | ERR_ABORT;
3334 goto out;
3335 }
3336
3337 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3338 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3339 file, linenum, args[0], args[1]);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003343 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3344 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3345 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003350 err_code |= warnif_cond_conflicts(cond,
3351 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3352 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003353
3354 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3355 rule->cond = cond;
3356 LIST_INIT(&rule->list);
3357 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 } else if (!strcmp(args[1], "uri")) {
3359 if (*(args[2]) == 0) {
3360 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3364 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_ABORT;
3366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
3368 } else if (!strcmp(args[1], "realm")) {
3369 if (*(args[2]) == 0) {
3370 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3374 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_ALERT | ERR_ABORT;
3376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003378 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003379 unsigned interval;
3380
3381 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3382 if (err) {
3383 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3384 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003387 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3388 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_ABORT;
3390 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003391 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003392 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003393 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003394
3395 if (curproxy == &defproxy) {
3396 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400
3401 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3403 err_code |= ERR_ALERT | ERR_ABORT;
3404 goto out;
3405 }
3406
Willy Tarreauff011f22011-01-06 17:51:27 +01003407 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3408 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003409 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3410 file, linenum, args[0]);
3411 err_code |= ERR_WARN;
3412 }
3413
Willy Tarreauff011f22011-01-06 17:51:27 +01003414 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003415
Willy Tarreauff011f22011-01-06 17:51:27 +01003416 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003417 err_code |= ERR_ALERT | ERR_ABORT;
3418 goto out;
3419 }
3420
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003421 err_code |= warnif_cond_conflicts(rule->cond,
3422 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3423 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003424 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003425
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 } else if (!strcmp(args[1], "auth")) {
3427 if (*(args[2]) == 0) {
3428 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3432 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_ABORT;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 }
3436 } else if (!strcmp(args[1], "scope")) {
3437 if (*(args[2]) == 0) {
3438 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_ABORT;
3444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 }
3446 } else if (!strcmp(args[1], "enable")) {
3447 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3448 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_ABORT;
3450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003452 } else if (!strcmp(args[1], "hide-version")) {
3453 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3454 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003455 err_code |= ERR_ALERT | ERR_ABORT;
3456 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003457 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003458 } else if (!strcmp(args[1], "show-legends")) {
3459 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3460 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3461 err_code |= ERR_ALERT | ERR_ABORT;
3462 goto out;
3463 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003464 } else if (!strcmp(args[1], "show-node")) {
3465
3466 if (*args[2]) {
3467 int i;
3468 char c;
3469
3470 for (i=0; args[2][i]; i++) {
3471 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003472 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3473 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003474 break;
3475 }
3476
3477 if (!i || args[2][i]) {
3478 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3479 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3480 file, linenum, args[0], args[1]);
3481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
3483 }
3484 }
3485
3486 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3487 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3488 err_code |= ERR_ALERT | ERR_ABORT;
3489 goto out;
3490 }
3491 } else if (!strcmp(args[1], "show-desc")) {
3492 char *desc = NULL;
3493
3494 if (*args[2]) {
3495 int i, len=0;
3496 char *d;
3497
Willy Tarreau348acfe2014-04-14 15:00:39 +02003498 for (i = 2; *args[i]; i++)
3499 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003500
3501 desc = d = (char *)calloc(1, len);
3502
Willy Tarreau348acfe2014-04-14 15:00:39 +02003503 d += snprintf(d, desc + len - d, "%s", args[2]);
3504 for (i = 3; *args[i]; i++)
3505 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003506 }
3507
3508 if (!*args[2] && !global.desc)
3509 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3510 file, linenum, args[1]);
3511 else {
3512 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3513 free(desc);
3514 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3515 err_code |= ERR_ALERT | ERR_ABORT;
3516 goto out;
3517 }
3518 free(desc);
3519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003521stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003522 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 +01003523 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 }
3527 }
3528 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003529 int optnum;
3530
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003531 if (*(args[1]) == '\0') {
3532 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3533 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003537
3538 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3539 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003540 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3541 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3542 file, linenum, cfg_opts[optnum].name);
3543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
3545 }
Willy Tarreau93893792009-07-23 13:19:11 +02003546 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3547 err_code |= ERR_WARN;
3548 goto out;
3549 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003550
Willy Tarreau3842f002009-06-14 11:39:52 +02003551 curproxy->no_options &= ~cfg_opts[optnum].val;
3552 curproxy->options &= ~cfg_opts[optnum].val;
3553
3554 switch (kwm) {
3555 case KWM_STD:
3556 curproxy->options |= cfg_opts[optnum].val;
3557 break;
3558 case KWM_NO:
3559 curproxy->no_options |= cfg_opts[optnum].val;
3560 break;
3561 case KWM_DEF: /* already cleared */
3562 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003563 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003564
Willy Tarreau93893792009-07-23 13:19:11 +02003565 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003566 }
3567 }
3568
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003569 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3570 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003571 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3572 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3573 file, linenum, cfg_opts2[optnum].name);
3574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
3576 }
Willy Tarreau93893792009-07-23 13:19:11 +02003577 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3578 err_code |= ERR_WARN;
3579 goto out;
3580 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003581
Willy Tarreau3842f002009-06-14 11:39:52 +02003582 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3583 curproxy->options2 &= ~cfg_opts2[optnum].val;
3584
3585 switch (kwm) {
3586 case KWM_STD:
3587 curproxy->options2 |= cfg_opts2[optnum].val;
3588 break;
3589 case KWM_NO:
3590 curproxy->no_options2 |= cfg_opts2[optnum].val;
3591 break;
3592 case KWM_DEF: /* already cleared */
3593 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003594 }
Willy Tarreau93893792009-07-23 13:19:11 +02003595 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003596 }
3597 }
3598
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003599 /* HTTP options override each other. They can be cancelled using
3600 * "no option xxx" which only switches to default mode if the mode
3601 * was this one (useful for cancelling options set in defaults
3602 * sections).
3603 */
3604 if (strcmp(args[1], "httpclose") == 0) {
3605 if (kwm == KWM_STD) {
3606 curproxy->options &= ~PR_O_HTTP_MODE;
3607 curproxy->options |= PR_O_HTTP_PCL;
3608 goto out;
3609 }
3610 else if (kwm == KWM_NO) {
3611 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3612 curproxy->options &= ~PR_O_HTTP_MODE;
3613 goto out;
3614 }
3615 }
3616 else if (strcmp(args[1], "forceclose") == 0) {
3617 if (kwm == KWM_STD) {
3618 curproxy->options &= ~PR_O_HTTP_MODE;
3619 curproxy->options |= PR_O_HTTP_FCL;
3620 goto out;
3621 }
3622 else if (kwm == KWM_NO) {
3623 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3624 curproxy->options &= ~PR_O_HTTP_MODE;
3625 goto out;
3626 }
3627 }
3628 else if (strcmp(args[1], "http-server-close") == 0) {
3629 if (kwm == KWM_STD) {
3630 curproxy->options &= ~PR_O_HTTP_MODE;
3631 curproxy->options |= PR_O_HTTP_SCL;
3632 goto out;
3633 }
3634 else if (kwm == KWM_NO) {
3635 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3636 curproxy->options &= ~PR_O_HTTP_MODE;
3637 goto out;
3638 }
3639 }
3640 else if (strcmp(args[1], "http-keep-alive") == 0) {
3641 if (kwm == KWM_STD) {
3642 curproxy->options &= ~PR_O_HTTP_MODE;
3643 curproxy->options |= PR_O_HTTP_KAL;
3644 goto out;
3645 }
3646 else if (kwm == KWM_NO) {
3647 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3648 curproxy->options &= ~PR_O_HTTP_MODE;
3649 goto out;
3650 }
3651 }
3652 else if (strcmp(args[1], "http-tunnel") == 0) {
3653 if (kwm == KWM_STD) {
3654 curproxy->options &= ~PR_O_HTTP_MODE;
3655 curproxy->options |= PR_O_HTTP_TUN;
3656 goto out;
3657 }
3658 else if (kwm == KWM_NO) {
3659 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3660 curproxy->options &= ~PR_O_HTTP_MODE;
3661 goto out;
3662 }
3663 }
3664
Willy Tarreau3842f002009-06-14 11:39:52 +02003665 if (kwm != KWM_STD) {
3666 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003667 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003670 }
3671
Emeric Brun3a058f32009-06-30 18:26:00 +02003672 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003673 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003674 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003675 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003676 if (*(args[2]) != '\0') {
3677 if (!strcmp(args[2], "clf")) {
3678 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003679 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003680 } else {
3681 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003684 }
3685 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003686 if (curproxy->conf.logformat_string != default_http_log_format &&
3687 curproxy->conf.logformat_string != default_tcp_log_format &&
3688 curproxy->conf.logformat_string != clf_http_log_format)
3689 free(curproxy->conf.logformat_string);
3690 curproxy->conf.logformat_string = logformat;
3691
3692 free(curproxy->conf.lfs_file);
3693 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3694 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003695 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003696 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003698 if (curproxy->conf.logformat_string != default_http_log_format &&
3699 curproxy->conf.logformat_string != default_tcp_log_format &&
3700 curproxy->conf.logformat_string != clf_http_log_format)
3701 free(curproxy->conf.logformat_string);
3702 curproxy->conf.logformat_string = default_tcp_log_format;
3703
3704 free(curproxy->conf.lfs_file);
3705 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3706 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 else if (!strcmp(args[1], "tcpka")) {
3709 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003710 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003712
3713 if (curproxy->cap & PR_CAP_FE)
3714 curproxy->options |= PR_O_TCP_CLI_KA;
3715 if (curproxy->cap & PR_CAP_BE)
3716 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 }
3718 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_WARN;
3721
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003723 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003724 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003725 curproxy->options2 &= ~PR_O2_CHK_ANY;
3726 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727 if (!*args[2]) { /* no argument */
3728 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3729 curproxy->check_len = strlen(DEF_CHECK_REQ);
3730 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003731 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 curproxy->check_req = (char *)malloc(reqlen);
3733 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003734 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003736 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 if (*args[4])
3738 reqlen += strlen(args[4]);
3739 else
3740 reqlen += strlen("HTTP/1.0");
3741
3742 curproxy->check_req = (char *)malloc(reqlen);
3743 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003744 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003746 }
3747 else if (!strcmp(args[1], "ssl-hello-chk")) {
3748 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003751
Willy Tarreaua534fea2008-08-03 12:19:50 +02003752 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003753 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003754 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003755 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 }
Willy Tarreau23677902007-05-08 23:50:35 +02003757 else if (!strcmp(args[1], "smtpchk")) {
3758 /* use SMTP request to check servers' health */
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;
3762 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003763
3764 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3765 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3766 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3767 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3768 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3769 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3770 curproxy->check_req = (char *)malloc(reqlen);
3771 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3772 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3773 } else {
3774 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3775 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3776 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3777 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3778 }
3779 }
3780 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003781 else if (!strcmp(args[1], "pgsql-check")) {
3782 /* use PostgreSQL request to check servers' health */
3783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3784 err_code |= ERR_WARN;
3785
3786 free(curproxy->check_req);
3787 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003788 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003789 curproxy->options2 |= PR_O2_PGSQL_CHK;
3790
3791 if (*(args[2])) {
3792 int cur_arg = 2;
3793
3794 while (*(args[cur_arg])) {
3795 if (strcmp(args[cur_arg], "user") == 0) {
3796 char * packet;
3797 uint32_t packet_len;
3798 uint32_t pv;
3799
3800 /* suboption header - needs additional argument for it */
3801 if (*(args[cur_arg+1]) == 0) {
3802 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3803 file, linenum, args[0], args[1], args[cur_arg]);
3804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
3806 }
3807
3808 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3809 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3810 pv = htonl(0x30000); /* protocol version 3.0 */
3811
3812 packet = (char*) calloc(1, packet_len);
3813
3814 memcpy(packet + 4, &pv, 4);
3815
3816 /* copy "user" */
3817 memcpy(packet + 8, "user", 4);
3818
3819 /* copy username */
3820 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3821
3822 free(curproxy->check_req);
3823 curproxy->check_req = packet;
3824 curproxy->check_len = packet_len;
3825
3826 packet_len = htonl(packet_len);
3827 memcpy(packet, &packet_len, 4);
3828 cur_arg += 2;
3829 } else {
3830 /* unknown suboption - catchall */
3831 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3832 file, linenum, args[0], args[1]);
3833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
3835 }
3836 } /* end while loop */
3837 }
3838 }
3839
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003840 else if (!strcmp(args[1], "redis-check")) {
3841 /* use REDIS PING request to check servers' health */
3842 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3843 err_code |= ERR_WARN;
3844
3845 free(curproxy->check_req);
3846 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003847 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003848 curproxy->options2 |= PR_O2_REDIS_CHK;
3849
3850 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3851 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3852 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3853 }
3854
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003855 else if (!strcmp(args[1], "mysql-check")) {
3856 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003857 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3858 err_code |= ERR_WARN;
3859
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003860 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003861 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003862 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003863 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003864
3865 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3866 * const char mysql40_client_auth_pkt[] = {
3867 * "\x0e\x00\x00" // packet length
3868 * "\x01" // packet number
3869 * "\x00\x00" // client capabilities
3870 * "\x00\x00\x01" // max packet
3871 * "haproxy\x00" // username (null terminated string)
3872 * "\x00" // filler (always 0x00)
3873 * "\x01\x00\x00" // packet length
3874 * "\x00" // packet number
3875 * "\x01" // COM_QUIT command
3876 * };
3877 */
3878
3879 if (*(args[2])) {
3880 int cur_arg = 2;
3881
3882 while (*(args[cur_arg])) {
3883 if (strcmp(args[cur_arg], "user") == 0) {
3884 char *mysqluser;
3885 int packetlen, reqlen, userlen;
3886
3887 /* suboption header - needs additional argument for it */
3888 if (*(args[cur_arg+1]) == 0) {
3889 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3890 file, linenum, args[0], args[1], args[cur_arg]);
3891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
3893 }
3894 mysqluser = args[cur_arg + 1];
3895 userlen = strlen(mysqluser);
3896 packetlen = userlen + 7;
3897 reqlen = packetlen + 9;
3898
3899 free(curproxy->check_req);
3900 curproxy->check_req = (char *)calloc(1, reqlen);
3901 curproxy->check_len = reqlen;
3902
3903 snprintf(curproxy->check_req, 4, "%c%c%c",
3904 ((unsigned char) packetlen & 0xff),
3905 ((unsigned char) (packetlen >> 8) & 0xff),
3906 ((unsigned char) (packetlen >> 16) & 0xff));
3907
3908 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003909 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003910 curproxy->check_req[8] = 1;
3911 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3912 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3913 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3914 cur_arg += 2;
3915 } else {
3916 /* unknown suboption - catchall */
3917 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3918 file, linenum, args[0], args[1]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922 } /* end while loop */
3923 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003924 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003925 else if (!strcmp(args[1], "ldap-check")) {
3926 /* use LDAP request to check servers' health */
3927 free(curproxy->check_req);
3928 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003929 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003930 curproxy->options2 |= PR_O2_LDAP_CHK;
3931
3932 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3933 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3934 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3935 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003936 else if (!strcmp(args[1], "tcp-check")) {
3937 /* use raw TCPCHK send/expect to check servers' health */
3938 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3939 err_code |= ERR_WARN;
3940
3941 free(curproxy->check_req);
3942 curproxy->check_req = NULL;
3943 curproxy->options2 &= ~PR_O2_CHK_ANY;
3944 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3945 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003946 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003947 int cur_arg;
3948
3949 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3950 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003951 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003952
Willy Tarreau87cf5142011-08-19 22:57:24 +02003953 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003954
3955 free(curproxy->fwdfor_hdr_name);
3956 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3957 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3958
3959 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3960 cur_arg = 2;
3961 while (*(args[cur_arg])) {
3962 if (!strcmp(args[cur_arg], "except")) {
3963 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003964 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003965 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3966 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003969 }
3970 /* flush useless bits */
3971 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003972 cur_arg += 2;
3973 } else if (!strcmp(args[cur_arg], "header")) {
3974 /* suboption header - needs additional argument for it */
3975 if (*(args[cur_arg+1]) == 0) {
3976 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3977 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003980 }
3981 free(curproxy->fwdfor_hdr_name);
3982 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3983 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3984 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003985 } else if (!strcmp(args[cur_arg], "if-none")) {
3986 curproxy->options &= ~PR_O_FF_ALWAYS;
3987 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003988 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003989 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003990 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003991 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003994 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003995 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003996 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003997 else if (!strcmp(args[1], "originalto")) {
3998 int cur_arg;
3999
4000 /* insert x-original-to field, but not for the IP address listed as an except.
4001 * set default options (ie: bitfield, header name, etc)
4002 */
4003
4004 curproxy->options |= PR_O_ORGTO;
4005
4006 free(curproxy->orgto_hdr_name);
4007 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4008 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4009
Willy Tarreau87cf5142011-08-19 22:57:24 +02004010 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004011 cur_arg = 2;
4012 while (*(args[cur_arg])) {
4013 if (!strcmp(args[cur_arg], "except")) {
4014 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004015 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 +02004016 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4017 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004020 }
4021 /* flush useless bits */
4022 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4023 cur_arg += 2;
4024 } else if (!strcmp(args[cur_arg], "header")) {
4025 /* suboption header - needs additional argument for it */
4026 if (*(args[cur_arg+1]) == 0) {
4027 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4028 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004031 }
4032 free(curproxy->orgto_hdr_name);
4033 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4034 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4035 cur_arg += 2;
4036 } else {
4037 /* unknown suboption - catchall */
4038 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4039 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004042 }
4043 } /* end while loop */
4044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 else {
4046 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 }
Willy Tarreau93893792009-07-23 13:19:11 +02004050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004052 else if (!strcmp(args[0], "default_backend")) {
4053 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004055
4056 if (*(args[1]) == 0) {
4057 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004060 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004061 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004062 curproxy->defbe.name = strdup(args[1]);
4063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004067
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004068 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4069 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 +01004070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 /* enable reconnections to dispatch */
4073 curproxy->options |= PR_O_REDISP;
4074 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004075 else if (!strcmp(args[0], "http-check")) {
4076 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004077 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004078
4079 if (strcmp(args[1], "disable-on-404") == 0) {
4080 /* enable a graceful server shutdown on an HTTP 404 response */
4081 curproxy->options |= PR_O_DISABLE404;
4082 }
Willy Tarreauef781042010-01-27 11:53:01 +01004083 else if (strcmp(args[1], "send-state") == 0) {
4084 /* enable emission of the apparent state of a server in HTTP checks */
4085 curproxy->options2 |= PR_O2_CHK_SNDST;
4086 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004087 else if (strcmp(args[1], "expect") == 0) {
4088 const char *ptr_arg;
4089 int cur_arg;
4090
4091 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4092 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096
4097 cur_arg = 2;
4098 /* consider exclamation marks, sole or at the beginning of a word */
4099 while (*(ptr_arg = args[cur_arg])) {
4100 while (*ptr_arg == '!') {
4101 curproxy->options2 ^= PR_O2_EXP_INV;
4102 ptr_arg++;
4103 }
4104 if (*ptr_arg)
4105 break;
4106 cur_arg++;
4107 }
4108 /* now ptr_arg points to the beginning of a word past any possible
4109 * exclamation mark, and cur_arg is the argument which holds this word.
4110 */
4111 if (strcmp(ptr_arg, "status") == 0) {
4112 if (!*(args[cur_arg + 1])) {
4113 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4114 file, linenum, args[0], args[1], ptr_arg);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004119 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004120 curproxy->expect_str = strdup(args[cur_arg + 1]);
4121 }
4122 else if (strcmp(ptr_arg, "string") == 0) {
4123 if (!*(args[cur_arg + 1])) {
4124 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4125 file, linenum, args[0], args[1], ptr_arg);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004130 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004131 curproxy->expect_str = strdup(args[cur_arg + 1]);
4132 }
4133 else if (strcmp(ptr_arg, "rstatus") == 0) {
4134 if (!*(args[cur_arg + 1])) {
4135 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4136 file, linenum, args[0], args[1], ptr_arg);
4137 err_code |= ERR_ALERT | ERR_FATAL;
4138 goto out;
4139 }
4140 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004141 free(curproxy->expect_str);
4142 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4143 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004144 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4145 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4146 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4147 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
4150 }
4151 }
4152 else if (strcmp(ptr_arg, "rstring") == 0) {
4153 if (!*(args[cur_arg + 1])) {
4154 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4155 file, linenum, args[0], args[1], ptr_arg);
4156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
4158 }
4159 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004160 free(curproxy->expect_str);
4161 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4162 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004163 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4164 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4165 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4166 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170 }
4171 else {
4172 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4173 file, linenum, args[0], args[1], ptr_arg);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
4177 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004178 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004179 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 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004182 }
4183 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004184 else if (!strcmp(args[0], "tcp-check")) {
4185 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4186 err_code |= ERR_WARN;
4187
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004188 if (strcmp(args[1], "connect") == 0) {
4189 const char *ptr_arg;
4190 int cur_arg;
4191 struct tcpcheck_rule *tcpcheck;
4192 struct list *l;
4193
4194 /* check if first rule is also a 'connect' action */
4195 l = (struct list *)&curproxy->tcpcheck_rules;
4196 if (l->p != l->n) {
4197 tcpcheck = (struct tcpcheck_rule *)l->n;
4198 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4199 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4200 file, linenum);
4201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
4203 }
4204 }
4205
4206 cur_arg = 2;
4207 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4208 tcpcheck->action = TCPCHK_ACT_CONNECT;
4209
4210 /* parsing each parameters to fill up the rule */
4211 while (*(ptr_arg = args[cur_arg])) {
4212 /* tcp port */
4213 if (strcmp(args[cur_arg], "port") == 0) {
4214 if ( (atol(args[cur_arg + 1]) > 65535) ||
4215 (atol(args[cur_arg + 1]) < 1) ){
4216 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4217 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220 }
4221 tcpcheck->port = atol(args[cur_arg + 1]);
4222 cur_arg += 2;
4223 }
4224 /* send proxy protocol */
4225 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4226 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4227 cur_arg++;
4228 }
4229#ifdef USE_OPENSSL
4230 else if (strcmp(args[cur_arg], "ssl") == 0) {
4231 curproxy->options |= PR_O_TCPCHK_SSL;
4232 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4233 cur_arg++;
4234 }
4235#endif /* USE_OPENSSL */
4236 else {
4237#ifdef USE_OPENSSL
4238 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4239#else /* USE_OPENSSL */
4240 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4241#endif /* USE_OPENSSL */
4242 file, linenum, args[0], args[1], args[cur_arg]);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
4245 }
4246
4247 }
4248
4249 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4250 }
4251 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004252 if (! *(args[2]) ) {
4253 /* SEND string expected */
4254 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4255 file, linenum, args[0], args[1], args[2]);
4256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
4258 } else {
4259 struct tcpcheck_rule *tcpcheck;
4260
4261 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4262
4263 tcpcheck->action = TCPCHK_ACT_SEND;
4264 tcpcheck->string_len = strlen(args[2]);
4265 tcpcheck->string = strdup(args[2]);
4266 tcpcheck->expect_regex = NULL;
4267
4268 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4269 }
4270 }
4271 else if (strcmp(args[1], "send-binary") == 0) {
4272 if (! *(args[2]) ) {
4273 /* SEND binary string expected */
4274 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4275 file, linenum, args[0], args[1], args[2]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 } else {
4279 struct tcpcheck_rule *tcpcheck;
4280 char *err = NULL;
4281
4282 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4283
4284 tcpcheck->action = TCPCHK_ACT_SEND;
4285 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4286 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4287 file, linenum, args[0], args[1], args[2], err);
4288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
4291 tcpcheck->expect_regex = NULL;
4292
4293 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4294 }
4295 }
4296 else if (strcmp(args[1], "expect") == 0) {
4297 const char *ptr_arg;
4298 int cur_arg;
4299 int inverse = 0;
4300
4301 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4302 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306
4307 cur_arg = 2;
4308 /* consider exclamation marks, sole or at the beginning of a word */
4309 while (*(ptr_arg = args[cur_arg])) {
4310 while (*ptr_arg == '!') {
4311 inverse = !inverse;
4312 ptr_arg++;
4313 }
4314 if (*ptr_arg)
4315 break;
4316 cur_arg++;
4317 }
4318 /* now ptr_arg points to the beginning of a word past any possible
4319 * exclamation mark, and cur_arg is the argument which holds this word.
4320 */
4321 if (strcmp(ptr_arg, "binary") == 0) {
4322 if (!*(args[cur_arg + 1])) {
4323 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4324 file, linenum, args[0], args[1], ptr_arg);
4325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
4327 }
4328 struct tcpcheck_rule *tcpcheck;
4329 char *err = NULL;
4330
4331 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4332
4333 tcpcheck->action = TCPCHK_ACT_EXPECT;
4334 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4335 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4336 file, linenum, args[0], args[1], args[2], err);
4337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
4339 }
4340 tcpcheck->expect_regex = NULL;
4341 tcpcheck->inverse = inverse;
4342
4343 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4344 }
4345 else if (strcmp(ptr_arg, "string") == 0) {
4346 if (!*(args[cur_arg + 1])) {
4347 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4348 file, linenum, args[0], args[1], ptr_arg);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352 struct tcpcheck_rule *tcpcheck;
4353
4354 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4355
4356 tcpcheck->action = TCPCHK_ACT_EXPECT;
4357 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4358 tcpcheck->string = strdup(args[cur_arg + 1]);
4359 tcpcheck->expect_regex = NULL;
4360 tcpcheck->inverse = inverse;
4361
4362 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4363 }
4364 else if (strcmp(ptr_arg, "rstring") == 0) {
4365 if (!*(args[cur_arg + 1])) {
4366 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4367 file, linenum, args[0], args[1], ptr_arg);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371 struct tcpcheck_rule *tcpcheck;
4372
4373 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4374
4375 tcpcheck->action = TCPCHK_ACT_EXPECT;
4376 tcpcheck->string_len = 0;
4377 tcpcheck->string = NULL;
4378 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4379 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4380 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4381 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
4384 }
4385 tcpcheck->inverse = inverse;
4386
4387 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4388 }
4389 else {
4390 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4391 file, linenum, args[0], args[1], ptr_arg);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395 }
4396 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004397 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004402 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004403 if (curproxy == &defproxy) {
4404 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004407 }
4408
Willy Tarreaub80c2302007-11-30 20:51:32 +01004409 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004411
4412 if (strcmp(args[1], "fail") == 0) {
4413 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004414 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004415 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4416 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004419 }
4420
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004421 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4422 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4423 file, linenum, args[0], args[1], errmsg);
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 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4428 }
4429 else {
4430 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435#ifdef TPROXY
4436 else if (!strcmp(args[0], "transparent")) {
4437 /* enable transparent proxy connections */
4438 curproxy->options |= PR_O_TRANSP;
4439 }
4440#endif
4441 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004442 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004444
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 if (*(args[1]) == 0) {
4446 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 }
4450 curproxy->maxconn = atol(args[1]);
4451 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004452 else if (!strcmp(args[0], "backlog")) { /* backlog */
4453 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004454 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004455
4456 if (*(args[1]) == 0) {
4457 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004460 }
4461 curproxy->backlog = atol(args[1]);
4462 }
Willy Tarreau86034312006-12-29 00:10:33 +01004463 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004464 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004466
Willy Tarreau86034312006-12-29 00:10:33 +01004467 if (*(args[1]) == 0) {
4468 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004471 }
4472 curproxy->fullconn = atol(args[1]);
4473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4475 if (*(args[1]) == 0) {
4476 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004480 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4481 if (err) {
4482 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4483 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004486 }
4487 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 }
4489 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004490 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004491 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004492 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004493
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 if (curproxy == &defproxy) {
4495 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004499 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004501
Willy Tarreau902636f2013-03-10 19:44:48 +01004502 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004503 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004504 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004505 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004506 goto out;
4507 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004508
4509 proto = protocol_by_family(sk->ss_family);
4510 if (!proto || !proto->connect) {
4511 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4512 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004513 err_code |= ERR_ALERT | ERR_FATAL;
4514 goto out;
4515 }
4516
4517 if (port1 != port2) {
4518 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4519 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004523
4524 if (!port1) {
4525 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4526 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
4529 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004530
Willy Tarreaud5191e72010-02-09 20:50:45 +01004531 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004532 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004533 }
4534 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004535 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004537
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004538 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4539 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004544 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004545 /**
4546 * The syntax for hash-type config element is
4547 * hash-type {map-based|consistent} [[<algo>] avalanche]
4548 *
4549 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4550 */
4551 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004552
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004553 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4554 err_code |= ERR_WARN;
4555
4556 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004557 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4558 }
4559 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004560 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4561 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004562 else if (strcmp(args[1], "avalanche") == 0) {
4563 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]);
4564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004566 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004567 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004568 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
4571 }
Bhaskar98634f02013-10-29 23:30:51 -04004572
4573 /* set the hash function to use */
4574 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004575 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004576 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004577
4578 /* if consistent with no argument, then avalanche modifier is also applied */
4579 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4580 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004581 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004582 /* set the hash function */
4583 if (!strcmp(args[2], "sdbm")) {
4584 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4585 }
4586 else if (!strcmp(args[2], "djb2")) {
4587 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004588 } else if (!strcmp(args[2], "wt6")) {
4589 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004590 }
4591 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004592 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 -05004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
4595 }
4596
4597 /* set the hash modifier */
4598 if (!strcmp(args[3], "avalanche")) {
4599 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4600 }
4601 else if (*args[3]) {
4602 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004606 }
William Lallemanda73203e2012-03-12 12:48:57 +01004607 }
William Lallemanda73203e2012-03-12 12:48:57 +01004608 else if (strcmp(args[0], "unique-id-format") == 0) {
4609 if (!*(args[1])) {
4610 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
William Lallemand3203ff42012-11-11 17:30:56 +01004614 if (*(args[2])) {
4615 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
4618 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004619 free(curproxy->conf.uniqueid_format_string);
4620 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004621
Willy Tarreau62a61232013-04-12 18:13:46 +02004622 free(curproxy->conf.uif_file);
4623 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4624 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004625 }
William Lallemanda73203e2012-03-12 12:48:57 +01004626
4627 else if (strcmp(args[0], "unique-id-header") == 0) {
4628 if (!*(args[1])) {
4629 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
4632 }
4633 free(curproxy->header_unique_id);
4634 curproxy->header_unique_id = strdup(args[1]);
4635 }
4636
William Lallemand723b73a2012-02-08 16:37:49 +01004637 else if (strcmp(args[0], "log-format") == 0) {
4638 if (!*(args[1])) {
4639 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
William Lallemand3203ff42012-11-11 17:30:56 +01004643 if (*(args[2])) {
4644 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
4647 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004648
Willy Tarreau62a61232013-04-12 18:13:46 +02004649 if (curproxy->conf.logformat_string != default_http_log_format &&
4650 curproxy->conf.logformat_string != default_tcp_log_format &&
4651 curproxy->conf.logformat_string != clf_http_log_format)
4652 free(curproxy->conf.logformat_string);
4653 curproxy->conf.logformat_string = strdup(args[1]);
4654
4655 free(curproxy->conf.lfs_file);
4656 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4657 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004658
4659 /* get a chance to improve log-format error reporting by
4660 * reporting the correct line-number when possible.
4661 */
4662 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4663 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4664 file, linenum, curproxy->id);
4665 err_code |= ERR_WARN;
4666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 }
William Lallemand723b73a2012-02-08 16:37:49 +01004668
William Lallemand0f99e342011-10-12 17:50:54 +02004669 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4670 /* delete previous herited or defined syslog servers */
4671 struct logsrv *back;
4672
4673 if (*(args[1]) != 0) {
4674 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
4677 }
4678
William Lallemand723b73a2012-02-08 16:37:49 +01004679 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4680 LIST_DEL(&tmplogsrv->list);
4681 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004682 }
4683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004685 struct logsrv *logsrv;
4686
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004688 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004689 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004690 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004691 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004692 LIST_INIT(&node->list);
4693 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 }
4696 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004697 struct sockaddr_storage *sk;
4698 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004699
4700 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701
William Lallemand0f99e342011-10-12 17:50:54 +02004702 logsrv->facility = get_log_facility(args[2]);
4703 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
4707
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
4709
William Lallemand0f99e342011-10-12 17:50:54 +02004710 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004712 logsrv->level = get_log_level(args[3]);
4713 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 }
4719 }
4720
William Lallemand0f99e342011-10-12 17:50:54 +02004721 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004722 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004723 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004724 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004725 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
4728
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004729 }
4730 }
4731
Willy Tarreau902636f2013-03-10 19:44:48 +01004732 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004733 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004734 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004735 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004736 goto out;
4737 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004738
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004739 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004740
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004741 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004742 if (port1 != port2) {
4743 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4744 file, linenum, args[0], args[1]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747 }
4748
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004749 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004750 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
William Lallemand0f99e342011-10-12 17:50:54 +02004752
4753 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
4755 else {
4756 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4757 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 }
4761 }
4762 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004763 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004764 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004765 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004766 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004767
Willy Tarreau977b8e42006-12-29 14:19:17 +01004768 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004769 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004770
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004772 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4773 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004777
4778 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004779 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4780 free(curproxy->conn_src.iface_name);
4781 curproxy->conn_src.iface_name = NULL;
4782 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004783
Willy Tarreau902636f2013-03-10 19:44:48 +01004784 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004785 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004786 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004787 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004788 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004789 goto out;
4790 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004791
4792 proto = protocol_by_family(sk->ss_family);
4793 if (!proto || !proto->connect) {
4794 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004795 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
4798 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004799
4800 if (port1 != port2) {
4801 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4802 file, linenum, args[0], args[1]);
4803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
4805 }
4806
Willy Tarreauef9a3602012-12-08 22:29:20 +01004807 curproxy->conn_src.source_addr = *sk;
4808 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004809
4810 cur_arg = 2;
4811 while (*(args[cur_arg])) {
4812 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004813#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4814#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004815 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004816 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4817 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004820 }
4821#endif
4822 if (!*args[cur_arg + 1]) {
4823 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\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
4829 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004830 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4831 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004832 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004833 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4834 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004835 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4836 char *name, *end;
4837
4838 name = args[cur_arg+1] + 7;
4839 while (isspace(*name))
4840 name++;
4841
4842 end = name;
4843 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4844 end++;
4845
Willy Tarreauef9a3602012-12-08 22:29:20 +01004846 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4847 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4848 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4849 curproxy->conn_src.bind_hdr_len = end - name;
4850 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4851 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4852 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004853
4854 /* now look for an occurrence number */
4855 while (isspace(*end))
4856 end++;
4857 if (*end == ',') {
4858 end++;
4859 name = end;
4860 if (*end == '-')
4861 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004862 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004863 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004864 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004865 }
4866
Willy Tarreauef9a3602012-12-08 22:29:20 +01004867 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004868 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4869 " occurrences values smaller than %d.\n",
4870 file, linenum, MAX_HDR_HISTORY);
4871 err_code |= ERR_ALERT | ERR_FATAL;
4872 goto out;
4873 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004874 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004875 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004876
Willy Tarreau902636f2013-03-10 19:44:48 +01004877 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004878 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004879 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004880 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004881 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004882 goto out;
4883 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004884
4885 proto = protocol_by_family(sk->ss_family);
4886 if (!proto || !proto->connect) {
4887 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4888 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
4891 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004892
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004893 if (port1 != port2) {
4894 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4895 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
4898 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004899 curproxy->conn_src.tproxy_addr = *sk;
4900 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004901 }
4902 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004903#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004904 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004905#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004906#else /* no TPROXY support */
4907 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004908 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004911#endif
4912 cur_arg += 2;
4913 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004914 }
4915
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004916 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4917#ifdef SO_BINDTODEVICE
4918 if (!*args[cur_arg + 1]) {
4919 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004923 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004924 free(curproxy->conn_src.iface_name);
4925 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4926 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004927 global.last_checks |= LSTCHK_NETADM;
4928#else
4929 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4930 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004933#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004934 cur_arg += 2;
4935 continue;
4936 }
4937 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004938 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004943 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4944 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4945 file, linenum, "usesrc", "source");
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 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4952 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956
4957 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004958 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004959 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
4963 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004965 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004966 args[0], args[1], NULL, (const char **)args+2);
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], "reqdeny")) { /* deny a request if a header matches this 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_DENY, 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], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 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], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004991 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02004997 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004998 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005001 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005003 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005004
5005 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5006 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 +01005007 }
5008 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005010 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005011 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005013 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005014
5015 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5016 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 +01005017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025
5026 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005027 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005028 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
5032 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005034 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005035 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 }
5039 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this 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_DENY, 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], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005047 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005048 SMP_OPT_DIR_REQ, ACT_PASS, 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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005054 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005055 SMP_OPT_DIR_REQ, ACT_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005060 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005068 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005069
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 if (curproxy == &defproxy) {
5071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005075 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 if (*(args[1]) == 0) {
5079 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005083
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005084 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005085 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5086 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5087 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
5090 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005091 err_code |= warnif_cond_conflicts(cond,
5092 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5093 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005094 }
5095 else if (*args[2]) {
5096 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5097 file, linenum, args[0], args[2]);
5098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
5100 }
5101
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005102 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005103 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005104 wl->s = strdup(args[1]);
5105 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005106 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 }
5108 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005115
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005117 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005118 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
5122 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
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_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005125 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
5129 else if (!strcmp(args[0], "rspdeny")) { /* block 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_DENY, 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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5139 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005145 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005146 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
5150 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
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_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005153 args[0], args[1], NULL, (const char **)args+2);
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], "rspideny")) { /* block 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_DENY, 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], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005165 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005166
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 if (curproxy == &defproxy) {
5168 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005172 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 if (*(args[1]) == 0) {
5176 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
5180
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005181 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005182 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5183 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5184 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
5187 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005188 err_code |= warnif_cond_conflicts(cond,
5189 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5190 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005191 }
5192 else if (*args[2]) {
5193 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5194 file, linenum, args[0], args[2]);
5195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
5197 }
5198
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005199 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005200 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005201 wl->s = strdup(args[1]);
5202 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
5204 else if (!strcmp(args[0], "errorloc") ||
5205 !strcmp(args[0], "errorloc302") ||
5206 !strcmp(args[0], "errorloc303")) { /* error location */
5207 int errnum, errlen;
5208 char *err;
5209
Willy Tarreau977b8e42006-12-29 14:19:17 +01005210 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005212
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005214 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
5218
5219 errnum = atol(args[1]);
5220 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005221 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5222 err = malloc(errlen);
5223 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005225 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5226 err = malloc(errlen);
5227 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 }
5229
Willy Tarreau0f772532006-12-23 20:51:41 +01005230 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5231 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005232 chunk_destroy(&curproxy->errmsg[rc]);
5233 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005234 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005237
5238 if (rc >= HTTP_ERR_SIZE) {
5239 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5240 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 free(err);
5242 }
5243 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005244 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5245 int errnum, errlen, fd;
5246 char *err;
5247 struct stat stat;
5248
5249 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005251
5252 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005253 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005254 err_code |= ERR_ALERT | ERR_FATAL;
5255 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005256 }
5257
5258 fd = open(args[2], O_RDONLY);
5259 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5260 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5261 file, linenum, args[2], args[1]);
5262 if (fd >= 0)
5263 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005266 }
5267
Willy Tarreau27a674e2009-08-17 07:23:33 +02005268 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005269 errlen = stat.st_size;
5270 } else {
5271 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005272 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005273 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005274 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005275 }
5276
5277 err = malloc(errlen); /* malloc() must succeed during parsing */
5278 errnum = read(fd, err, errlen);
5279 if (errnum != errlen) {
5280 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5281 file, linenum, args[2], args[1]);
5282 close(fd);
5283 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005284 err_code |= ERR_ALERT | ERR_FATAL;
5285 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005286 }
5287 close(fd);
5288
5289 errnum = atol(args[1]);
5290 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5291 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005292 chunk_destroy(&curproxy->errmsg[rc]);
5293 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005294 break;
5295 }
5296 }
5297
5298 if (rc >= HTTP_ERR_SIZE) {
5299 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5300 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005301 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005302 free(err);
5303 }
5304 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005305 else if (!strcmp(args[0], "compression")) {
5306 struct comp *comp;
5307 if (curproxy->comp == NULL) {
5308 comp = calloc(1, sizeof(struct comp));
5309 curproxy->comp = comp;
5310 } else {
5311 comp = curproxy->comp;
5312 }
5313
5314 if (!strcmp(args[1], "algo")) {
5315 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005316 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005317
William Lallemand82fe75c2012-10-23 10:25:10 +02005318 cur_arg = 2;
5319 if (!*args[cur_arg]) {
5320 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5321 file, linenum, args[0]);
5322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
5325 while (*(args[cur_arg])) {
5326 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5327 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5328 file, linenum, args[0], args[cur_arg]);
5329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
5331 }
William Lallemand552df672012-11-07 13:21:47 +01005332 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5333 curproxy->comp->algos->end(&ctx);
5334 } else {
5335 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5336 file, linenum, args[0], args[cur_arg]);
5337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
5339 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005340 cur_arg ++;
5341 continue;
5342 }
5343 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005344 else if (!strcmp(args[1], "offload")) {
5345 comp->offload = 1;
5346 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005347 else if (!strcmp(args[1], "type")) {
5348 int cur_arg;
5349 cur_arg = 2;
5350 if (!*args[cur_arg]) {
5351 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5352 file, linenum, args[0]);
5353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
5355 }
5356 while (*(args[cur_arg])) {
5357 comp_append_type(comp, args[cur_arg]);
5358 cur_arg ++;
5359 continue;
5360 }
5361 }
5362 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005363 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005364 file, linenum, args[0]);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005370 struct cfg_kw_list *kwl;
5371 int index;
5372
5373 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5374 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5375 if (kwl->kw[index].section != CFG_LISTEN)
5376 continue;
5377 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5378 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005379 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005380 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005381 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005384 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005385 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005386 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_WARN;
5388 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005389 }
Willy Tarreau93893792009-07-23 13:19:11 +02005390 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005391 }
5392 }
5393 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005394
Willy Tarreau6daf3432008-01-22 16:44:08 +01005395 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 }
Willy Tarreau93893792009-07-23 13:19:11 +02005399 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005400 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005401 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402}
5403
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005404int
5405cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5406{
5407
5408 int err_code = 0;
5409 const char *err;
5410
5411 if (!strcmp(args[0], "userlist")) { /* new userlist */
5412 struct userlist *newul;
5413
5414 if (!*args[1]) {
5415 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5416 file, linenum, args[0]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420
5421 err = invalid_char(args[1]);
5422 if (err) {
5423 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5424 file, linenum, *err, args[0], args[1]);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
5428
5429 for (newul = userlist; newul; newul = newul->next)
5430 if (!strcmp(newul->name, args[1])) {
5431 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5432 file, linenum, args[1]);
5433 err_code |= ERR_WARN;
5434 goto out;
5435 }
5436
5437 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5438 if (!newul) {
5439 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5440 err_code |= ERR_ALERT | ERR_ABORT;
5441 goto out;
5442 }
5443
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005444 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005445 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005446 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5447 err_code |= ERR_ALERT | ERR_ABORT;
5448 goto out;
5449 }
5450
5451 newul->next = userlist;
5452 userlist = newul;
5453
5454 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005455 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005456 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005457 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005458
5459 if (!*args[1]) {
5460 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5461 file, linenum, args[0]);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
5465
5466 err = invalid_char(args[1]);
5467 if (err) {
5468 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5469 file, linenum, *err, args[0], args[1]);
5470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
5472 }
5473
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005474 for (ag = userlist->groups; ag; ag = ag->next)
5475 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005476 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5477 file, linenum, args[1], userlist->name);
5478 err_code |= ERR_ALERT;
5479 goto out;
5480 }
5481
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005482 ag = calloc(1, sizeof(*ag));
5483 if (!ag) {
5484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5485 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005486 goto out;
5487 }
5488
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005489 ag->name = strdup(args[1]);
5490 if (!ag) {
5491 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5492 err_code |= ERR_ALERT | ERR_ABORT;
5493 goto out;
5494 }
5495
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005496 cur_arg = 2;
5497
5498 while (*args[cur_arg]) {
5499 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005500 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005501 cur_arg += 2;
5502 continue;
5503 } else {
5504 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5505 file, linenum, args[0]);
5506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
5508 }
5509 }
5510
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005511 ag->next = userlist->groups;
5512 userlist->groups = ag;
5513
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005514 } else if (!strcmp(args[0], "user")) { /* new user */
5515 struct auth_users *newuser;
5516 int cur_arg;
5517
5518 if (!*args[1]) {
5519 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5520 file, linenum, args[0]);
5521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
5523 }
5524
5525 for (newuser = userlist->users; newuser; newuser = newuser->next)
5526 if (!strcmp(newuser->user, args[1])) {
5527 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5528 file, linenum, args[1], userlist->name);
5529 err_code |= ERR_ALERT;
5530 goto out;
5531 }
5532
5533 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5534 if (!newuser) {
5535 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5536 err_code |= ERR_ALERT | ERR_ABORT;
5537 goto out;
5538 }
5539
5540 newuser->user = strdup(args[1]);
5541
5542 newuser->next = userlist->users;
5543 userlist->users = newuser;
5544
5545 cur_arg = 2;
5546
5547 while (*args[cur_arg]) {
5548 if (!strcmp(args[cur_arg], "password")) {
5549#ifndef CONFIG_HAP_CRYPT
5550 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5551 file, linenum);
5552 err_code |= ERR_ALERT;
5553#endif
5554 newuser->pass = strdup(args[cur_arg + 1]);
5555 cur_arg += 2;
5556 continue;
5557 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5558 newuser->pass = strdup(args[cur_arg + 1]);
5559 newuser->flags |= AU_O_INSECURE;
5560 cur_arg += 2;
5561 continue;
5562 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005563 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005564 cur_arg += 2;
5565 continue;
5566 } else {
5567 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5568 file, linenum, args[0]);
5569 err_code |= ERR_ALERT | ERR_FATAL;
5570 goto out;
5571 }
5572 }
5573 } else {
5574 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 }
5577
5578out:
5579 return err_code;
5580}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581
5582/*
5583 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005584 * Returns the error code, 0 if OK, or any combination of :
5585 * - ERR_ABORT: must abort ASAP
5586 * - ERR_FATAL: we can continue parsing but not start the service
5587 * - ERR_WARN: a warning has been emitted
5588 * - ERR_ALERT: an alert has been emitted
5589 * Only the two first ones can stop processing, the two others are just
5590 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005592int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005594 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 FILE *f;
5596 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005597 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005598 struct cfg_section *cs = NULL;
5599 struct cfg_section *ics;
5600
5601 /* Register internal sections */
5602 if (!cfg_register_section("listen", cfg_parse_listen) ||
5603 !cfg_register_section("frontend", cfg_parse_listen) ||
5604 !cfg_register_section("backend", cfg_parse_listen) ||
5605 !cfg_register_section("ruleset", cfg_parse_listen) ||
5606 !cfg_register_section("defaults", cfg_parse_listen) ||
5607 !cfg_register_section("global", cfg_parse_global) ||
5608 !cfg_register_section("userlist", cfg_parse_users) ||
5609 !cfg_register_section("peers", cfg_parse_peers))
5610 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 if ((f=fopen(file,"r")) == NULL)
5613 return -1;
5614
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005615 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005616 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005617 char *end;
5618 char *args[MAX_LINE_ARGS + 1];
5619 char *line = thisline;
5620
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 linenum++;
5622
5623 end = line + strlen(line);
5624
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005625 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5626 /* Check if we reached the limit and the last char is not \n.
5627 * Watch out for the last line without the terminating '\n'!
5628 */
5629 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005630 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005631 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005632 }
5633
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005635 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 line++;
5637
5638 arg = 0;
5639 args[arg] = line;
5640
5641 while (*line && arg < MAX_LINE_ARGS) {
5642 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5643 * C equivalent value. Other combinations left unchanged (eg: \1).
5644 */
5645 if (*line == '\\') {
5646 int skip = 0;
5647 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5648 *line = line[1];
5649 skip = 1;
5650 }
5651 else if (line[1] == 'r') {
5652 *line = '\r';
5653 skip = 1;
5654 }
5655 else if (line[1] == 'n') {
5656 *line = '\n';
5657 skip = 1;
5658 }
5659 else if (line[1] == 't') {
5660 *line = '\t';
5661 skip = 1;
5662 }
5663 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005664 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 unsigned char hex1, hex2;
5666 hex1 = toupper(line[2]) - '0';
5667 hex2 = toupper(line[3]) - '0';
5668 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5669 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5670 *line = (hex1<<4) + hex2;
5671 skip = 3;
5672 }
5673 else {
5674 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005675 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
5677 }
5678 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005679 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 end -= skip;
5681 }
5682 line++;
5683 }
5684 else if (*line == '#' || *line == '\n' || *line == '\r') {
5685 /* end of string, end of loop */
5686 *line = 0;
5687 break;
5688 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005689 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005691 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005692 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 line++;
5694 args[++arg] = line;
5695 }
5696 else {
5697 line++;
5698 }
5699 }
5700
5701 /* empty line */
5702 if (!**args)
5703 continue;
5704
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005705 if (*line) {
5706 /* we had to stop due to too many args.
5707 * Let's terminate the string, print the offending part then cut the
5708 * last arg.
5709 */
5710 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5711 line++;
5712 *line = '\0';
5713
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005714 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005715 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005716 err_code |= ERR_ALERT | ERR_FATAL;
5717 args[arg] = line;
5718 }
5719
Willy Tarreau540abe42007-05-02 20:50:16 +02005720 /* zero out remaining args and ensure that at least one entry
5721 * is zeroed out.
5722 */
5723 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 args[arg] = line;
5725 }
5726
Willy Tarreau3842f002009-06-14 11:39:52 +02005727 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005728 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005729 char *tmp;
5730
Willy Tarreau3842f002009-06-14 11:39:52 +02005731 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005732 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005733 for (arg=0; *args[arg+1]; arg++)
5734 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005735 *tmp = '\0'; // fix the next arg to \0
5736 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005737 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005738 else if (!strcmp(args[0], "default")) {
5739 kwm = KWM_DEF;
5740 for (arg=0; *args[arg+1]; arg++)
5741 args[arg] = args[arg+1]; // shift args after inversion
5742 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005743
William Lallemand0f99e342011-10-12 17:50:54 +02005744 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5745 strcmp(args[0], "log") != 0) {
5746 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005747 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005748 }
5749
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005750 /* detect section start */
5751 list_for_each_entry(ics, &sections, list) {
5752 if (strcmp(args[0], ics->section_name) == 0) {
5753 cursection = ics->section_name;
5754 cs = ics;
5755 break;
5756 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005757 }
5758
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005760 if (cs)
5761 err_code |= cs->section_parser(file, linenum, args, kwm);
5762 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005763 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005764 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005766
5767 if (err_code & ERR_ABORT)
5768 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005770 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005772 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005773}
5774
Willy Tarreaubb925012009-07-23 13:36:36 +02005775/*
5776 * Returns the error code, 0 if OK, or any combination of :
5777 * - ERR_ABORT: must abort ASAP
5778 * - ERR_FATAL: we can continue parsing but not start the service
5779 * - ERR_WARN: a warning has been emitted
5780 * - ERR_ALERT: an alert has been emitted
5781 * Only the two first ones can stop processing, the two others are just
5782 * indicators.
5783 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005784int check_config_validity()
5785{
5786 int cfgerr = 0;
5787 struct proxy *curproxy = NULL;
5788 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005789 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005790 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005791 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005793 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 /*
5795 * Now, check for the integrity of all that we have collected.
5796 */
5797
5798 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005799 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800
Willy Tarreau193b8c62012-11-22 00:17:38 +01005801 if (!global.tune.max_http_hdr)
5802 global.tune.max_http_hdr = MAX_HTTP_HDR;
5803
5804 if (!global.tune.cookie_len)
5805 global.tune.cookie_len = CAPTURE_LEN;
5806
5807 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5808
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005809 /* Post initialisation of the users and groups lists. */
5810 err_code = userlist_postinit();
5811 if (err_code != ERR_NONE)
5812 goto out;
5813
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005814 /* first, we will invert the proxy list order */
5815 curproxy = NULL;
5816 while (proxy) {
5817 struct proxy *next;
5818
5819 next = proxy->next;
5820 proxy->next = curproxy;
5821 curproxy = proxy;
5822 if (!next)
5823 break;
5824 proxy = next;
5825 }
5826
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005828 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005829 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005830 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005831 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005832 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005833 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005834 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005835
Willy Tarreau050536d2012-10-04 08:47:34 +02005836 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005837 /* proxy ID not set, use automatic numbering with first
5838 * spare entry starting with next_pxid.
5839 */
5840 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5841 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5842 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005843 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005844 next_pxid++;
5845
Willy Tarreau55ea7572007-06-17 19:56:27 +02005846
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005848 /* ensure we don't keep listeners uselessly bound */
5849 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850 curproxy = curproxy->next;
5851 continue;
5852 }
5853
Willy Tarreau102df612014-05-07 23:56:38 +02005854 /* Check multi-process mode compatibility for the current proxy */
5855
5856 if (curproxy->bind_proc) {
5857 /* an explicit bind-process was specified, let's check how many
5858 * processes remain.
5859 */
5860 nbproc = popcount(curproxy->bind_proc);
5861
5862 curproxy->bind_proc &= nbits(global.nbproc);
5863 if (!curproxy->bind_proc && nbproc == 1) {
5864 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);
5865 curproxy->bind_proc = 1;
5866 }
5867 else if (!curproxy->bind_proc && nbproc > 1) {
5868 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);
5869 curproxy->bind_proc = 0;
5870 }
5871 }
5872
Willy Tarreau3d209582014-05-09 17:06:11 +02005873 /* check and reduce the bind-proc of each listener */
5874 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
5875 unsigned long mask;
5876
5877 if (!bind_conf->bind_proc)
5878 continue;
5879
5880 mask = nbits(global.nbproc);
5881 if (curproxy->bind_proc)
5882 mask &= curproxy->bind_proc;
5883 /* mask cannot be null here thanks to the previous checks */
5884
5885 nbproc = popcount(bind_conf->bind_proc);
5886 bind_conf->bind_proc &= mask;
5887
5888 if (!bind_conf->bind_proc && nbproc == 1) {
5889 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",
5890 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5891 bind_conf->bind_proc = mask & ~(mask - 1);
5892 }
5893 else if (!bind_conf->bind_proc && nbproc > 1) {
5894 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",
5895 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5896 bind_conf->bind_proc = 0;
5897 }
5898 }
5899
Willy Tarreau102df612014-05-07 23:56:38 +02005900 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
5901 * We now check how many processes the proxy will effectively run on.
5902 */
5903
5904 nbproc = global.nbproc;
5905 if (curproxy->bind_proc)
5906 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
5907
5908 if (global.nbproc > 1 && curproxy->table.peers.name) {
5909 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
5910 curproxy->id);
5911 cfgerr++;
5912 }
Willy Tarreau16a21472012-11-19 12:39:59 +01005913
Willy Tarreauff01a212009-03-15 13:46:16 +01005914 switch (curproxy->mode) {
5915 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005916 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005917 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005918 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5919 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005920 cfgerr++;
5921 }
5922
5923 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005924 Warning("config : servers will be ignored for %s '%s'.\n",
5925 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005926 break;
5927
5928 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005929 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005930 break;
5931
5932 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005933 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005934 break;
5935 }
5936
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005937 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005938 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005939 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005940 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5941 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005942 cfgerr++;
5943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005945 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005946 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5947 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005948 cfgerr++;
5949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005951 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005952 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5953 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005954 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005955 }
5956 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005957 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005958 /* If no LB algo is set in a backend, and we're not in
5959 * transparent mode, dispatch mode nor proxy mode, we
5960 * want to use balance roundrobin by default.
5961 */
5962 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5963 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 }
5965 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005966
Willy Tarreau1620ec32011-08-06 17:05:02 +02005967 if (curproxy->options & PR_O_DISPATCH)
5968 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5969 else if (curproxy->options & PR_O_HTTP_PROXY)
5970 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5971 else if (curproxy->options & PR_O_TRANSP)
5972 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005973
Willy Tarreau1620ec32011-08-06 17:05:02 +02005974 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5975 if (curproxy->options & PR_O_DISABLE404) {
5976 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5977 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5978 err_code |= ERR_WARN;
5979 curproxy->options &= ~PR_O_DISABLE404;
5980 }
5981 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5982 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5983 "send-state", proxy_type_str(curproxy), curproxy->id);
5984 err_code |= ERR_WARN;
5985 curproxy->options &= ~PR_O2_CHK_SNDST;
5986 }
Willy Tarreauef781042010-01-27 11:53:01 +01005987 }
5988
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005989 /* if a default backend was specified, let's find it */
5990 if (curproxy->defbe.name) {
5991 struct proxy *target;
5992
Alex Williams96532db2009-11-01 21:27:13 -05005993 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005994 if (!target) {
5995 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5996 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005997 cfgerr++;
5998 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005999 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6000 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006001 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006002 } else {
6003 free(curproxy->defbe.name);
6004 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006005 /* we force the backend to be present on at least all of
6006 * the frontend's processes.
6007 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006008 if (target->bind_proc)
6009 target->bind_proc = curproxy->bind_proc ?
6010 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006011
6012 /* Emit a warning if this proxy also has some servers */
6013 if (curproxy->srv) {
6014 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6015 curproxy->id);
6016 err_code |= ERR_WARN;
6017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018 }
6019 }
6020
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006021 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006022 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6023 /* map jump target for ACT_SETBE in req_rep chain */
6024 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006025 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006026 struct proxy *target;
6027
Willy Tarreaua496b602006-12-17 23:15:24 +01006028 if (exp->action != ACT_SETBE)
6029 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006030
Alex Williams96532db2009-11-01 21:27:13 -05006031 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006032 if (!target) {
6033 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6034 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006035 cfgerr++;
6036 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006037 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6038 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006039 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006040 } else {
6041 free((void *)exp->replace);
6042 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006043 /* we force the backend to be present on at least all of
6044 * the frontend's processes.
6045 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006046 if (target->bind_proc)
6047 target->bind_proc = curproxy->bind_proc ?
6048 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006049 }
6050 }
6051 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006052
6053 /* find the target proxy for 'use_backend' rules */
6054 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006055 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006056 struct logformat_node *node;
6057 char *pxname;
6058
6059 /* Try to parse the string as a log format expression. If the result
6060 * of the parsing is only one entry containing a simple string, then
6061 * it's a standard string corresponding to a static rule, thus the
6062 * parsing is cancelled and be.name is restored to be resolved.
6063 */
6064 pxname = rule->be.name;
6065 LIST_INIT(&rule->be.expr);
6066 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6067 curproxy->conf.args.file, curproxy->conf.args.line);
6068 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6069
6070 if (!LIST_ISEMPTY(&rule->be.expr)) {
6071 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6072 rule->dynamic = 1;
6073 free(pxname);
6074 continue;
6075 }
6076 /* simple string: free the expression and fall back to static rule */
6077 free(node->arg);
6078 free(node);
6079 }
6080
6081 rule->dynamic = 0;
6082 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006083
Alex Williams96532db2009-11-01 21:27:13 -05006084 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006085
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006086 if (!target) {
6087 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6088 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006089 cfgerr++;
6090 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006091 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6092 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006093 cfgerr++;
6094 } else {
6095 free((void *)rule->be.name);
6096 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006097 /* we force the backend to be present on at least all of
6098 * the frontend's processes.
6099 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006100 if (target->bind_proc)
6101 target->bind_proc = curproxy->bind_proc ?
6102 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006103 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006104 }
6105
6106 /* find the target proxy for 'use_backend' rules */
6107 list_for_each_entry(srule, &curproxy->server_rules, list) {
6108 struct server *target = findserver(curproxy, srule->srv.name);
6109
6110 if (!target) {
6111 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6112 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6113 cfgerr++;
6114 continue;
6115 }
6116 free((void *)srule->srv.name);
6117 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006118 }
6119
Emeric Brunb982a3d2010-01-04 15:45:53 +01006120 /* find the target table for 'stick' rules */
6121 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6122 struct proxy *target;
6123
Emeric Brun1d33b292010-01-04 15:47:17 +01006124 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6125 if (mrule->flags & STK_IS_STORE)
6126 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6127
Emeric Brunb982a3d2010-01-04 15:45:53 +01006128 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006129 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006130 else
6131 target = curproxy;
6132
6133 if (!target) {
6134 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6135 curproxy->id, mrule->table.name);
6136 cfgerr++;
6137 }
6138 else if (target->table.size == 0) {
6139 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6140 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6141 cfgerr++;
6142 }
Willy Tarreau12785782012-04-27 21:37:17 +02006143 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6144 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006145 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6146 cfgerr++;
6147 }
6148 else {
6149 free((void *)mrule->table.name);
6150 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006151 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006152 }
6153 }
6154
6155 /* find the target table for 'store response' rules */
6156 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6157 struct proxy *target;
6158
Emeric Brun1d33b292010-01-04 15:47:17 +01006159 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6160
Emeric Brunb982a3d2010-01-04 15:45:53 +01006161 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006162 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006163 else
6164 target = curproxy;
6165
6166 if (!target) {
6167 Alert("Proxy '%s': unable to find store table '%s'.\n",
6168 curproxy->id, mrule->table.name);
6169 cfgerr++;
6170 }
6171 else if (target->table.size == 0) {
6172 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6173 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6174 cfgerr++;
6175 }
Willy Tarreau12785782012-04-27 21:37:17 +02006176 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6177 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006178 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6179 cfgerr++;
6180 }
6181 else {
6182 free((void *)mrule->table.name);
6183 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006184 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006185 }
6186 }
6187
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006188 /* find the target table for 'tcp-request' layer 4 rules */
6189 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6190 struct proxy *target;
6191
Willy Tarreaub4c84932013-07-23 19:15:30 +02006192 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006193 continue;
6194
6195 if (trule->act_prm.trk_ctr.table.n)
6196 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6197 else
6198 target = curproxy;
6199
6200 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006201 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6202 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006203 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006204 cfgerr++;
6205 }
6206 else if (target->table.size == 0) {
6207 Alert("Proxy '%s': table '%s' used but not configured.\n",
6208 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6209 cfgerr++;
6210 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006211 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6212 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6213 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 +01006214 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006215 cfgerr++;
6216 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006217 else {
6218 free(trule->act_prm.trk_ctr.table.n);
6219 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006220 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006221 * to pass a list of counters to track and allocate them right here using
6222 * stktable_alloc_data_type().
6223 */
6224 }
6225 }
6226
Willy Tarreaud1f96522010-08-03 19:34:32 +02006227 /* find the target table for 'tcp-request' layer 6 rules */
6228 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6229 struct proxy *target;
6230
Willy Tarreaub4c84932013-07-23 19:15:30 +02006231 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006232 continue;
6233
6234 if (trule->act_prm.trk_ctr.table.n)
6235 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6236 else
6237 target = curproxy;
6238
6239 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006240 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6241 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006242 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006243 cfgerr++;
6244 }
6245 else if (target->table.size == 0) {
6246 Alert("Proxy '%s': table '%s' used but not configured.\n",
6247 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6248 cfgerr++;
6249 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006250 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6251 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6252 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 +01006253 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006254 cfgerr++;
6255 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006256 else {
6257 free(trule->act_prm.trk_ctr.table.n);
6258 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006259 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006260 * to pass a list of counters to track and allocate them right here using
6261 * stktable_alloc_data_type().
6262 */
6263 }
6264 }
6265
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006266 /* move any "block" rules at the beginning of the http-request rules */
6267 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6268 /* insert block_rules into http_req_rules at the beginning */
6269 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6270 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6271 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6272 curproxy->http_req_rules.n = curproxy->block_rules.n;
6273 LIST_INIT(&curproxy->block_rules);
6274 }
6275
Emeric Brun32da3c42010-09-23 18:39:19 +02006276 if (curproxy->table.peers.name) {
6277 struct peers *curpeers = peers;
6278
6279 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6280 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6281 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006282 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006283 break;
6284 }
6285 }
6286
6287 if (!curpeers) {
6288 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6289 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006290 free((void *)curproxy->table.peers.name);
6291 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006292 cfgerr++;
6293 }
6294 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006295 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6296 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006297 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006298 cfgerr++;
6299 }
6300 }
6301
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006302 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006303 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006304 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6305 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6306 "proxy", curproxy->id);
6307 cfgerr++;
6308 goto out_uri_auth_compat;
6309 }
6310
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006311 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006312 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006313 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006314 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006315
Willy Tarreau95fa4692010-02-01 13:05:50 +01006316 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6317 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006318
6319 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006320 uri_auth_compat_req[i++] = "realm";
6321 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6322 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006323
Willy Tarreau95fa4692010-02-01 13:05:50 +01006324 uri_auth_compat_req[i++] = "unless";
6325 uri_auth_compat_req[i++] = "{";
6326 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6327 uri_auth_compat_req[i++] = "}";
6328 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006329
Willy Tarreauff011f22011-01-06 17:51:27 +01006330 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6331 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006332 cfgerr++;
6333 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006334 }
6335
Willy Tarreauff011f22011-01-06 17:51:27 +01006336 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006337
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006338 if (curproxy->uri_auth->auth_realm) {
6339 free(curproxy->uri_auth->auth_realm);
6340 curproxy->uri_auth->auth_realm = NULL;
6341 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006342
6343 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006344 }
6345out_uri_auth_compat:
6346
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006347 /* compile the log format */
6348 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006349 if (curproxy->conf.logformat_string != default_http_log_format &&
6350 curproxy->conf.logformat_string != default_tcp_log_format &&
6351 curproxy->conf.logformat_string != clf_http_log_format)
6352 free(curproxy->conf.logformat_string);
6353 curproxy->conf.logformat_string = NULL;
6354 free(curproxy->conf.lfs_file);
6355 curproxy->conf.lfs_file = NULL;
6356 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006357 }
6358
Willy Tarreau62a61232013-04-12 18:13:46 +02006359 if (curproxy->conf.logformat_string) {
6360 curproxy->conf.args.ctx = ARGC_LOG;
6361 curproxy->conf.args.file = curproxy->conf.lfs_file;
6362 curproxy->conf.args.line = curproxy->conf.lfs_line;
6363 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006364 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006365 curproxy->conf.args.file = NULL;
6366 curproxy->conf.args.line = 0;
6367 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006368
Willy Tarreau62a61232013-04-12 18:13:46 +02006369 if (curproxy->conf.uniqueid_format_string) {
6370 curproxy->conf.args.ctx = ARGC_UIF;
6371 curproxy->conf.args.file = curproxy->conf.uif_file;
6372 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006373 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006374 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6375 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006376 curproxy->conf.args.file = NULL;
6377 curproxy->conf.args.line = 0;
6378 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006379
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006380 /* only now we can check if some args remain unresolved.
6381 * This must be done after the users and groups resolution.
6382 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006383 cfgerr += smp_resolve_args(curproxy);
6384 if (!cfgerr)
6385 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006386
Willy Tarreau2738a142006-07-08 17:28:09 +02006387 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006388 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006389 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006390 (!curproxy->timeout.connect ||
6391 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006392 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006393 " | While not properly invalid, you will certainly encounter various problems\n"
6394 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006395 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006396 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006397 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006398 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006399
Willy Tarreau1fa31262007-12-03 00:36:16 +01006400 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6401 * We must still support older configurations, so let's find out whether those
6402 * parameters have been set or must be copied from contimeouts.
6403 */
6404 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006405 if (!curproxy->timeout.tarpit ||
6406 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006407 /* tarpit timeout not set. We search in the following order:
6408 * default.tarpit, curr.connect, default.connect.
6409 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006410 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006411 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006412 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006413 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006414 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006415 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006416 }
6417 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006418 (!curproxy->timeout.queue ||
6419 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006420 /* queue timeout not set. We search in the following order:
6421 * default.queue, curr.connect, default.connect.
6422 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006423 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006424 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006425 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006426 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006427 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006428 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006429 }
6430 }
6431
Willy Tarreau1620ec32011-08-06 17:05:02 +02006432 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006433 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6434 curproxy->check_req = (char *)malloc(curproxy->check_len);
6435 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006436 }
6437
Willy Tarreau193b8c62012-11-22 00:17:38 +01006438 /* ensure that cookie capture length is not too large */
6439 if (curproxy->capture_len >= global.tune.cookie_len) {
6440 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6441 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6442 err_code |= ERR_WARN;
6443 curproxy->capture_len = global.tune.cookie_len - 1;
6444 }
6445
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006446 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006447 if (curproxy->nb_req_cap) {
6448 if (curproxy->mode == PR_MODE_HTTP) {
6449 curproxy->req_cap_pool = create_pool("ptrcap",
6450 curproxy->nb_req_cap * sizeof(char *),
6451 MEM_F_SHARED);
6452 } else {
6453 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6454 proxy_type_str(curproxy), curproxy->id);
6455 err_code |= ERR_WARN;
6456 curproxy->to_log &= ~LW_REQHDR;
6457 curproxy->nb_req_cap = 0;
6458 }
6459 }
6460
6461 if (curproxy->nb_rsp_cap) {
6462 if (curproxy->mode == PR_MODE_HTTP) {
6463 curproxy->rsp_cap_pool = create_pool("ptrcap",
6464 curproxy->nb_rsp_cap * sizeof(char *),
6465 MEM_F_SHARED);
6466 } else {
6467 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6468 proxy_type_str(curproxy), curproxy->id);
6469 err_code |= ERR_WARN;
6470 curproxy->to_log &= ~LW_REQHDR;
6471 curproxy->nb_rsp_cap = 0;
6472 }
6473 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006474
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 /* first, we will invert the servers list order */
6476 newsrv = NULL;
6477 while (curproxy->srv) {
6478 struct server *next;
6479
6480 next = curproxy->srv->next;
6481 curproxy->srv->next = newsrv;
6482 newsrv = curproxy->srv;
6483 if (!next)
6484 break;
6485 curproxy->srv = next;
6486 }
6487
Willy Tarreau17edc812014-01-03 12:14:34 +01006488 /* Check that no server name conflicts. This causes trouble in the stats.
6489 * We only emit a warning for the first conflict affecting each server,
6490 * in order to avoid combinatory explosion if all servers have the same
6491 * name. We do that only for servers which do not have an explicit ID,
6492 * because these IDs were made also for distinguishing them and we don't
6493 * want to annoy people who correctly manage them.
6494 */
6495 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6496 struct server *other_srv;
6497
6498 if (newsrv->puid)
6499 continue;
6500
6501 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6502 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6503 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6504 newsrv->conf.file, newsrv->conf.line,
6505 proxy_type_str(curproxy), curproxy->id,
6506 newsrv->id, other_srv->conf.line);
6507 break;
6508 }
6509 }
6510 }
6511
Willy Tarreaudd701652010-05-25 23:03:02 +02006512 /* assign automatic UIDs to servers which don't have one yet */
6513 next_id = 1;
6514 newsrv = curproxy->srv;
6515 while (newsrv != NULL) {
6516 if (!newsrv->puid) {
6517 /* server ID not set, use automatic numbering with first
6518 * spare entry starting with next_svid.
6519 */
6520 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6521 newsrv->conf.id.key = newsrv->puid = next_id;
6522 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6523 }
6524 next_id++;
6525 newsrv = newsrv->next;
6526 }
6527
Willy Tarreau20697042007-11-15 23:26:18 +01006528 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006529 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530
Willy Tarreau62c3be22012-01-20 13:12:32 +01006531 /*
6532 * If this server supports a maxconn parameter, it needs a dedicated
6533 * tasks to fill the emptied slots when a connection leaves.
6534 * Also, resolve deferred tracking dependency if needed.
6535 */
6536 newsrv = curproxy->srv;
6537 while (newsrv != NULL) {
6538 if (newsrv->minconn > newsrv->maxconn) {
6539 /* Only 'minconn' was specified, or it was higher than or equal
6540 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6541 * this will avoid further useless expensive computations.
6542 */
6543 newsrv->maxconn = newsrv->minconn;
6544 } else if (newsrv->maxconn && !newsrv->minconn) {
6545 /* minconn was not specified, so we set it to maxconn */
6546 newsrv->minconn = newsrv->maxconn;
6547 }
6548
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006549#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006550 if (newsrv->use_ssl || newsrv->check.use_ssl)
6551 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006552#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006553
Willy Tarreau2f075e92013-12-03 11:11:34 +01006554 /* set the check type on the server */
6555 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6556
Willy Tarreau62c3be22012-01-20 13:12:32 +01006557 if (newsrv->trackit) {
6558 struct proxy *px;
6559 struct server *srv;
6560 char *pname, *sname;
6561
6562 pname = newsrv->trackit;
6563 sname = strrchr(pname, '/');
6564
6565 if (sname)
6566 *sname++ = '\0';
6567 else {
6568 sname = pname;
6569 pname = NULL;
6570 }
6571
6572 if (pname) {
6573 px = findproxy(pname, PR_CAP_BE);
6574 if (!px) {
6575 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6576 proxy_type_str(curproxy), curproxy->id,
6577 newsrv->id, pname);
6578 cfgerr++;
6579 goto next_srv;
6580 }
6581 } else
6582 px = curproxy;
6583
6584 srv = findserver(px, sname);
6585 if (!srv) {
6586 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6587 proxy_type_str(curproxy), curproxy->id,
6588 newsrv->id, sname);
6589 cfgerr++;
6590 goto next_srv;
6591 }
6592
Willy Tarreauff5ae352013-12-11 20:36:34 +01006593 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006594 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6595 "tracking as it does not have checks enabled.\n",
6596 proxy_type_str(curproxy), curproxy->id,
6597 newsrv->id, px->id, srv->id);
6598 cfgerr++;
6599 goto next_srv;
6600 }
6601
6602 if (curproxy != px &&
6603 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6604 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6605 "tracking: disable-on-404 option inconsistency.\n",
6606 proxy_type_str(curproxy), curproxy->id,
6607 newsrv->id, px->id, srv->id);
6608 cfgerr++;
6609 goto next_srv;
6610 }
6611
6612 /* if the other server is forced disabled, we have to do the same here */
6613 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006614 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006615 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006616 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006617 }
6618
6619 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006620 newsrv->tracknext = srv->trackers;
6621 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006622
6623 free(newsrv->trackit);
6624 newsrv->trackit = NULL;
6625 }
6626 next_srv:
6627 newsrv = newsrv->next;
6628 }
6629
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006630 /* We have to initialize the server lookup mechanism depending
6631 * on what LB algorithm was choosen.
6632 */
6633
6634 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6635 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6636 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006637 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6638 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6639 init_server_map(curproxy);
6640 } else {
6641 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6642 fwrr_init_server_groups(curproxy);
6643 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006644 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006645
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006646 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006647 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6648 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6649 fwlc_init_server_tree(curproxy);
6650 } else {
6651 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6652 fas_init_server_tree(curproxy);
6653 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006654 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006655
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006656 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006657 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6658 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6659 chash_init_server_tree(curproxy);
6660 } else {
6661 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6662 init_server_map(curproxy);
6663 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006664 break;
6665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006666
6667 if (curproxy->options & PR_O_LOGASAP)
6668 curproxy->to_log &= ~LW_BYTES;
6669
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006670 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006671 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006672 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6673 proxy_type_str(curproxy), curproxy->id);
6674 err_code |= ERR_WARN;
6675 }
6676
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006677 if (curproxy->mode != PR_MODE_HTTP) {
6678 int optnum;
6679
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006680 if (curproxy->uri_auth) {
6681 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6682 proxy_type_str(curproxy), curproxy->id);
6683 err_code |= ERR_WARN;
6684 curproxy->uri_auth = NULL;
6685 }
6686
Willy Tarreau87cf5142011-08-19 22:57:24 +02006687 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006688 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6689 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6690 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006691 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006692 }
6693
6694 if (curproxy->options & PR_O_ORGTO) {
6695 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6696 "originalto", proxy_type_str(curproxy), curproxy->id);
6697 err_code |= ERR_WARN;
6698 curproxy->options &= ~PR_O_ORGTO;
6699 }
6700
6701 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6702 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6703 (curproxy->cap & cfg_opts[optnum].cap) &&
6704 (curproxy->options & cfg_opts[optnum].val)) {
6705 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6706 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6707 err_code |= ERR_WARN;
6708 curproxy->options &= ~cfg_opts[optnum].val;
6709 }
6710 }
6711
6712 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6713 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6714 (curproxy->cap & cfg_opts2[optnum].cap) &&
6715 (curproxy->options2 & cfg_opts2[optnum].val)) {
6716 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6717 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6718 err_code |= ERR_WARN;
6719 curproxy->options2 &= ~cfg_opts2[optnum].val;
6720 }
6721 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006722
Pieter Baauwd551fb52013-05-08 22:49:23 +02006723#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006724 if (curproxy->conn_src.bind_hdr_occ) {
6725 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006726 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006727 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006728 err_code |= ERR_WARN;
6729 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006730#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006731 }
6732
Willy Tarreaubaaee002006-06-26 02:48:02 +02006733 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006734 * ensure that we're not cross-dressing a TCP server into HTTP.
6735 */
6736 newsrv = curproxy->srv;
6737 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006738 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006739 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6740 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006741 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006742 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006743
Willy Tarreau0cec3312011-10-31 13:49:26 +01006744 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6745 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6746 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6747 err_code |= ERR_WARN;
6748 }
6749
Willy Tarreau82ffa392013-08-13 17:19:08 +02006750 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6751 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6752 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6753 err_code |= ERR_WARN;
6754 }
6755
Pieter Baauwd551fb52013-05-08 22:49:23 +02006756#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006757 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6758 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006759 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 +01006760 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006761 err_code |= ERR_WARN;
6762 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006763#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006764 newsrv = newsrv->next;
6765 }
6766
Willy Tarreauc1a21672009-08-16 22:37:44 +02006767 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006768 if (!curproxy->accept)
6769 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006770
Willy Tarreauc1a21672009-08-16 22:37:44 +02006771 if (curproxy->tcp_req.inspect_delay ||
6772 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006773 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006774
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006775 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006776 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006777 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006778 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006779
6780 /* both TCP and HTTP must check switching rules */
6781 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6782 }
6783
6784 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006785 if (curproxy->tcp_req.inspect_delay ||
6786 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6787 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6788
Emeric Brun97679e72010-09-23 17:56:44 +02006789 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6790 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6791
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006792 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006793 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006794 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006795 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006796
6797 /* If the backend does requires RDP cookie persistence, we have to
6798 * enable the corresponding analyser.
6799 */
6800 if (curproxy->options2 & PR_O2_RDPC_PRST)
6801 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6802 }
6803
Emeric Brunc52962f2012-11-15 18:28:02 +01006804#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006805 /* Configure SSL for each bind line.
6806 * Note: if configuration fails at some point, the ->ctx member
6807 * remains NULL so that listeners can later detach.
6808 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006809 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006810 int alloc_ctx;
6811
Emeric Brunc52962f2012-11-15 18:28:02 +01006812 if (!bind_conf->is_ssl) {
6813 if (bind_conf->default_ctx) {
6814 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6815 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6816 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006817 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006818 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006819 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006820 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006821 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006822 cfgerr++;
6823 continue;
6824 }
6825
Emeric Brun8dc60392014-05-09 13:52:00 +02006826 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006827 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02006828 if (alloc_ctx == SHCTX_E_INIT_LOCK)
6829 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");
6830 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006831 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02006832 cfgerr++;
6833 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006834 }
6835
Emeric Brunfc0421f2012-09-07 17:30:07 +02006836 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006837 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006838 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006839#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006840
Willy Tarreaue6b98942007-10-29 01:09:36 +01006841 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006842 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006843 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006844 if (!listener->luid) {
6845 /* listener ID not set, use automatic numbering with first
6846 * spare entry starting with next_luid.
6847 */
6848 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6849 listener->conf.id.key = listener->luid = next_id;
6850 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006851 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006852 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006853
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006854 /* enable separate counters */
6855 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6856 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006857 if (!listener->name)
6858 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006859 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006860
Willy Tarreaue6b98942007-10-29 01:09:36 +01006861 if (curproxy->options & PR_O_TCP_NOLING)
6862 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006863 if (!listener->maxconn)
6864 listener->maxconn = curproxy->maxconn;
6865 if (!listener->backlog)
6866 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006867 if (!listener->maxaccept)
6868 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6869
6870 /* we want to have an optimal behaviour on single process mode to
6871 * maximize the work at once, but in multi-process we want to keep
6872 * some fairness between processes, so we target half of the max
6873 * number of events to be balanced over all the processes the proxy
6874 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6875 * used to disable the limit.
6876 */
6877 if (listener->maxaccept > 0) {
6878 if (nbproc > 1)
6879 listener->maxaccept = (listener->maxaccept + 1) / 2;
6880 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6881 }
6882
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006883 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006884 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006885 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006886 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006887
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006888 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6889 listener->options |= LI_O_TCP_RULES;
6890
Willy Tarreaude3041d2010-05-31 10:56:17 +02006891 if (curproxy->mon_mask.s_addr)
6892 listener->options |= LI_O_CHK_MONNET;
6893
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006894 /* smart accept mode is automatic in HTTP mode */
6895 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006896 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006897 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6898 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006899 }
6900
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006901 /* Release unused SSL configs */
6902 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6903 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006904 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006905#ifdef USE_OPENSSL
6906 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006907 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006908 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006909 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006910 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006911#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006912 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006913
Willy Tarreau102df612014-05-07 23:56:38 +02006914 if (nbproc > 1) {
6915 if (curproxy->uri_auth) {
6916 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6917 curproxy->id);
6918 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6919 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6920 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006921 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006922 }
Willy Tarreau102df612014-05-07 23:56:38 +02006923 if (curproxy->appsession_name) {
6924 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6925 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006926 }
Willy Tarreau102df612014-05-07 23:56:38 +02006927 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6928 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6929 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006930 }
6931 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006932
6933 /* create the task associated with the proxy */
6934 curproxy->task = task_new();
6935 if (curproxy->task) {
6936 curproxy->task->context = curproxy;
6937 curproxy->task->process = manage_proxy;
6938 /* no need to queue, it will be done automatically if some
6939 * listener gets limited.
6940 */
6941 curproxy->task->expire = TICK_ETERNITY;
6942 } else {
6943 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6944 curproxy->id);
6945 cfgerr++;
6946 }
6947
Willy Tarreaubaaee002006-06-26 02:48:02 +02006948 curproxy = curproxy->next;
6949 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006950
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006951 /* Check multi-process mode compatibility */
6952 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006953 if (global.stats_fe && !global.stats_fe->bind_proc) {
6954 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding using 'stats bind-process'.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006955 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006956 }
6957
6958 /* automatically compute fullconn if not set. We must not do it in the
6959 * loop above because cross-references are not yet fully resolved.
6960 */
6961 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6962 /* If <fullconn> is not set, let's set it to 10% of the sum of
6963 * the possible incoming frontend's maxconns.
6964 */
6965 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6966 struct proxy *fe;
6967 int total = 0;
6968
6969 /* sum up the number of maxconns of frontends which
6970 * reference this backend at least once or which are
6971 * the same one ('listen').
6972 */
6973 for (fe = proxy; fe; fe = fe->next) {
6974 struct switching_rule *rule;
6975 struct hdr_exp *exp;
6976 int found = 0;
6977
6978 if (!(fe->cap & PR_CAP_FE))
6979 continue;
6980
6981 if (fe == curproxy) /* we're on a "listen" instance */
6982 found = 1;
6983
6984 if (fe->defbe.be == curproxy) /* "default_backend" */
6985 found = 1;
6986
6987 /* check if a "use_backend" rule matches */
6988 if (!found) {
6989 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006990 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006991 found = 1;
6992 break;
6993 }
6994 }
6995 }
6996
6997 /* check if a "reqsetbe" rule matches */
6998 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6999 if (exp->action == ACT_SETBE &&
7000 (struct proxy *)exp->replace == curproxy) {
7001 found = 1;
7002 break;
7003 }
7004 }
7005
7006 /* now we've checked all possible ways to reference a backend
7007 * from a frontend.
7008 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007009 if (!found)
7010 continue;
7011 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007012 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007013 /* we have the sum of the maxconns in <total>. We only
7014 * keep 10% of that sum to set the default fullconn, with
7015 * a hard minimum of 1 (to avoid a divide by zero).
7016 */
7017 curproxy->fullconn = (total + 9) / 10;
7018 if (!curproxy->fullconn)
7019 curproxy->fullconn = 1;
7020 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007021 }
7022
Willy Tarreau056f5682010-06-06 15:51:11 +02007023 /* initialize stick-tables on backend capable proxies. This must not
7024 * be done earlier because the data size may be discovered while parsing
7025 * other proxies.
7026 */
Godbach9703e662013-12-11 21:11:41 +08007027 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007028 if (curproxy->state == PR_STSTOPPED)
7029 continue;
7030
Godbach9703e662013-12-11 21:11:41 +08007031 if (!stktable_init(&curproxy->table)) {
7032 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7033 cfgerr++;
7034 }
7035 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007036
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007037 /*
7038 * Recount currently required checks.
7039 */
7040
7041 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7042 int optnum;
7043
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007044 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7045 if (curproxy->options & cfg_opts[optnum].val)
7046 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007047
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007048 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7049 if (curproxy->options2 & cfg_opts2[optnum].val)
7050 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007051 }
7052
Willy Tarreau122541c2011-09-07 21:24:49 +02007053 if (peers) {
7054 struct peers *curpeers = peers, **last;
7055 struct peer *p, *pb;
7056
7057 /* Remove all peers sections which don't have a valid listener.
7058 * This can happen when a peers section is never referenced and
7059 * does not contain a local peer.
7060 */
7061 last = &peers;
7062 while (*last) {
7063 curpeers = *last;
7064 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007065 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007066 last = &curpeers->next;
7067 continue;
7068 }
7069
7070 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7071 curpeers->id, localpeer);
7072
7073 p = curpeers->remote;
7074 while (p) {
7075 pb = p->next;
7076 free(p->id);
7077 free(p);
7078 p = pb;
7079 }
7080
7081 /* Destroy and unlink this curpeers section.
7082 * Note: curpeers is backed up into *last.
7083 */
7084 free(curpeers->id);
7085 curpeers = curpeers->next;
7086 free(*last);
7087 *last = curpeers;
7088 }
7089 }
7090
Willy Tarreau34eb6712011-10-24 18:15:04 +02007091 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007092 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007093 MEM_F_SHARED);
7094
Willy Tarreaubb925012009-07-23 13:36:36 +02007095 if (cfgerr > 0)
7096 err_code |= ERR_ALERT | ERR_FATAL;
7097 out:
7098 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007099}
7100
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007101/*
7102 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7103 * parsing sessions.
7104 */
7105void cfg_register_keywords(struct cfg_kw_list *kwl)
7106{
7107 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7108}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007110/*
7111 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7112 */
7113void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7114{
7115 LIST_DEL(&kwl->list);
7116 LIST_INIT(&kwl->list);
7117}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007118
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007119/* this function register new section in the haproxy configuration file.
7120 * <section_name> is the name of this new section and <section_parser>
7121 * is the called parser. If two section declaration have the same name,
7122 * only the first declared is used.
7123 */
7124int cfg_register_section(char *section_name,
7125 int (*section_parser)(const char *, int, char **, int))
7126{
7127 struct cfg_section *cs;
7128
7129 cs = calloc(1, sizeof(*cs));
7130 if (!cs) {
7131 Alert("register section '%s': out of memory.\n", section_name);
7132 return 0;
7133 }
7134
7135 cs->section_name = section_name;
7136 cs->section_parser = section_parser;
7137
7138 LIST_ADDQ(&sections, &cs->list);
7139
7140 return 1;
7141}
7142
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143/*
7144 * Local variables:
7145 * c-indent-level: 8
7146 * c-basic-offset: 8
7147 * End:
7148 */