blob: d4893a1345b4e1a63ef0ea4b2e2e385302f544c3 [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{
315 if (!LIST_ISEMPTY(&proxy->block_cond)) {
316 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
323/* Report a warning if a rule is placed after a reqrewrite rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200327{
328 if (proxy->req_exp) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
336/* Report a warning if a rule is placed after a reqadd rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100341 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' 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 redirect rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
354 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' 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 'use_backend' rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' 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 block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
378 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
379 warnif_rule_after_reqadd(proxy, file, line, arg) ||
380 warnif_rule_after_redirect(proxy, file, line, arg) ||
381 warnif_rule_after_use_backend(proxy, file, line, arg);
382}
383
384/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100385int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200386{
387 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100399/* Report it if a request ACL condition uses some keywords that are incompatible
400 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
401 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
402 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100403 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100404static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100405{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100406 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200407 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100408
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100409 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100410 return 0;
411
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100412 acl = acl_cond_conflicts(cond, where);
413 if (acl) {
414 if (acl->name && *acl->name)
415 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
416 file, line, acl->name, sample_ckp_names(where));
417 else
418 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 +0200419 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100420 return ERR_WARN;
421 }
422 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100423 return 0;
424
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100425 if (acl->name && *acl->name)
426 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200427 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100428 else
429 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200430 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100431 return ERR_WARN;
432}
433
Willy Tarreaubaaee002006-06-26 02:48:02 +0200434/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200435 * parse a line in a <global> section. Returns the error code, 0 if OK, or
436 * any combination of :
437 * - ERR_ABORT: must abort ASAP
438 * - ERR_FATAL: we can continue parsing but not start the service
439 * - ERR_WARN: a warning has been emitted
440 * - ERR_ALERT: an alert has been emitted
441 * Only the two first ones can stop processing, the two others are just
442 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200444int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200445{
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200447 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200448
449 if (!strcmp(args[0], "global")) { /* new section */
450 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200453 else if (!strcmp(args[0], "ca-base")) {
454#ifdef USE_OPENSSL
455 if (global.ca_base != NULL) {
456 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
457 err_code |= ERR_ALERT;
458 goto out;
459 }
460 if (*(args[1]) == 0) {
461 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
462 err_code |= ERR_ALERT | ERR_FATAL;
463 goto out;
464 }
465 global.ca_base = strdup(args[1]);
466#else
467 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
468 err_code |= ERR_ALERT | ERR_FATAL;
469 goto out;
470#endif
471 }
472 else if (!strcmp(args[0], "crt-base")) {
473#ifdef USE_OPENSSL
474 if (global.crt_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.crt_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491 else if (!strcmp(args[0], "daemon")) {
492 global.mode |= MODE_DAEMON;
493 }
494 else if (!strcmp(args[0], "debug")) {
495 global.mode |= MODE_DEBUG;
496 }
497 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100498 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200500 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100501 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100504 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100506 else if (!strcmp(args[0], "nosplice")) {
507 global.tune.options &= ~GTUNE_USE_SPLICE;
508 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200509 else if (!strcmp(args[0], "nogetaddrinfo")) {
510 global.tune.options &= ~GTUNE_USE_GAI;
511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200512 else if (!strcmp(args[0], "quiet")) {
513 global.mode |= MODE_QUIET;
514 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200515 else if (!strcmp(args[0], "tune.maxpollevents")) {
516 if (global.tune.maxpollevents != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200518 err_code |= ERR_ALERT;
519 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200525 }
526 global.tune.maxpollevents = atol(args[1]);
527 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100528 else if (!strcmp(args[0], "tune.maxaccept")) {
529 if (global.tune.maxaccept != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 err_code |= ERR_ALERT;
532 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100538 }
539 global.tune.maxaccept = atol(args[1]);
540 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200541 else if (!strcmp(args[0], "tune.chksize")) {
542 if (*(args[1]) == 0) {
543 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
546 }
547 global.tune.chksize = atol(args[1]);
548 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200549#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100550 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 global.tune.sslcachesize = atol(args[1]);
557 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100558 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
559 unsigned int ssllifetime;
560 const char *res;
561
562 if (*(args[1]) == 0) {
563 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566 }
567
568 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
569 if (res) {
570 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
571 file, linenum, *res, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575
576 global.tune.ssllifetime = ssllifetime;
577 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100578 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
579 if (*(args[1]) == 0) {
580 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT | ERR_FATAL;
582 goto out;
583 }
584 global.tune.ssl_max_record = atol(args[1]);
585 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200586#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200587 else if (!strcmp(args[0], "tune.bufsize")) {
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
592 }
593 global.tune.bufsize = atol(args[1]);
594 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
595 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100596 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100597 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200598 }
599 else if (!strcmp(args[0], "tune.maxrewrite")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.maxrewrite = atol(args[1]);
606 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
607 global.tune.maxrewrite = global.tune.bufsize / 2;
608 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100609 else if (!strcmp(args[0], "tune.idletimer")) {
610 unsigned int idle;
611 const char *res;
612
613 if (*(args[1]) == 0) {
614 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT | ERR_FATAL;
616 goto out;
617 }
618
619 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
620 if (res) {
621 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
622 file, linenum, *res, args[0]);
623 err_code |= ERR_ALERT | ERR_FATAL;
624 goto out;
625 }
626
627 if (idle > 65535) {
628 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631 }
632 global.tune.idle_timer = idle;
633 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100634 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
635 if (global.tune.client_rcvbuf != 0) {
636 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT;
638 goto out;
639 }
640 if (*(args[1]) == 0) {
641 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
642 err_code |= ERR_ALERT | ERR_FATAL;
643 goto out;
644 }
645 global.tune.client_rcvbuf = atol(args[1]);
646 }
647 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
648 if (global.tune.server_rcvbuf != 0) {
649 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT;
651 goto out;
652 }
653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.server_rcvbuf = atol(args[1]);
659 }
660 else if (!strcmp(args[0], "tune.sndbuf.client")) {
661 if (global.tune.client_sndbuf != 0) {
662 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT;
664 goto out;
665 }
666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
670 }
671 global.tune.client_sndbuf = atol(args[1]);
672 }
673 else if (!strcmp(args[0], "tune.sndbuf.server")) {
674 if (global.tune.server_sndbuf != 0) {
675 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT;
677 goto out;
678 }
679 if (*(args[1]) == 0) {
680 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
681 err_code |= ERR_ALERT | ERR_FATAL;
682 goto out;
683 }
684 global.tune.server_sndbuf = atol(args[1]);
685 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200686 else if (!strcmp(args[0], "tune.pipesize")) {
687 if (*(args[1]) == 0) {
688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
691 }
692 global.tune.pipesize = atol(args[1]);
693 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100694 else if (!strcmp(args[0], "tune.http.cookielen")) {
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
699 }
700 global.tune.cookie_len = atol(args[1]) + 1;
701 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200702 else if (!strcmp(args[0], "tune.http.maxhdr")) {
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.max_http_hdr = atol(args[1]);
709 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100710 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
711#ifdef USE_ZLIB
712 if (*args[1]) {
713 global.tune.zlibmemlevel = atoi(args[1]);
714 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
715 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
716 file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 } else {
721 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
722 file, linenum, args[0]);
723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
725 }
726#else
727 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730#endif
731 }
732 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
733#ifdef USE_ZLIB
734 if (*args[1]) {
735 global.tune.zlibwindowsize = atoi(args[1]);
736 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
737 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
738 file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 } else {
743 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
744 file, linenum, args[0]);
745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
747 }
748#else
749 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
752#endif
753 }
William Lallemandf3747832012-11-09 12:33:10 +0100754 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
755 if (*args[1]) {
756 global.tune.comp_maxlevel = atoi(args[1]);
757 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
758 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
759 file, linenum, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 } else {
764 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
765 file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 else if (!strcmp(args[0], "uid")) {
771 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200772 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
781 global.uid = atol(args[1]);
782 }
783 else if (!strcmp(args[0], "gid")) {
784 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200786 err_code |= ERR_ALERT;
787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788 }
789 if (*(args[1]) == 0) {
790 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 }
794 global.gid = atol(args[1]);
795 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200796 /* user/group name handling */
797 else if (!strcmp(args[0], "user")) {
798 struct passwd *ha_user;
799 if (global.uid != 0) {
800 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200801 err_code |= ERR_ALERT;
802 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200803 }
804 errno = 0;
805 ha_user = getpwnam(args[1]);
806 if (ha_user != NULL) {
807 global.uid = (int)ha_user->pw_uid;
808 }
809 else {
810 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 +0200811 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200812 }
813 }
814 else if (!strcmp(args[0], "group")) {
815 struct group *ha_group;
816 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200817 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200818 err_code |= ERR_ALERT;
819 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200820 }
821 errno = 0;
822 ha_group = getgrnam(args[1]);
823 if (ha_group != NULL) {
824 global.gid = (int)ha_group->gr_gid;
825 }
826 else {
827 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 +0200828 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200829 }
830 }
831 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 if (*(args[1]) == 0) {
834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 }
838 global.nbproc = atol(args[1]);
839 }
840 else if (!strcmp(args[0], "maxconn")) {
841 if (global.maxconn != 0) {
842 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT;
844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 }
846 if (*(args[1]) == 0) {
847 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200848 err_code |= ERR_ALERT | ERR_FATAL;
849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200850 }
851 global.maxconn = atol(args[1]);
852#ifdef SYSTEM_MAXCONN
853 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
854 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);
855 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200856 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858#endif /* SYSTEM_MAXCONN */
859 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200860 else if (!strcmp(args[0], "maxsslconn")) {
861#ifdef USE_OPENSSL
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 global.maxsslconn = atol(args[1]);
868#else
Emeric Brun0914df82012-10-02 18:45:42 +0200869 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200872#endif
873 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100874 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
875#ifdef USE_OPENSSL
876 if (*(args[1]) == 0) {
877 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 free(global.listen_default_ciphers);
882 global.listen_default_ciphers = strdup(args[1]);
883#else
884 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887#endif
888 }
889 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
890#ifdef USE_OPENSSL
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
896 free(global.connect_default_ciphers);
897 global.connect_default_ciphers = strdup(args[1]);
898#else
899 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902#endif
903 }
Emeric Brun850efd52014-01-29 12:24:34 +0100904 else if (!strcmp(args[0], "ssl-server-verify")) {
905 if (*(args[1]) == 0) {
906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910 if (strcmp(args[1],"none") == 0)
911 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
912 else if (strcmp(args[1],"required") == 0)
913 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
914 else {
915 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200920 else if (!strcmp(args[0], "maxconnrate")) {
921 if (global.cps_lim != 0) {
922 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
923 err_code |= ERR_ALERT;
924 goto out;
925 }
926 if (*(args[1]) == 0) {
927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 global.cps_lim = atol(args[1]);
932 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200933 else if (!strcmp(args[0], "maxsessrate")) {
934 if (global.sps_lim != 0) {
935 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT;
937 goto out;
938 }
939 if (*(args[1]) == 0) {
940 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 global.sps_lim = atol(args[1]);
945 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200946 else if (!strcmp(args[0], "maxsslrate")) {
947 if (global.ssl_lim != 0) {
948 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT;
950 goto out;
951 }
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957 global.ssl_lim = atol(args[1]);
958 }
William Lallemandd85f9172012-11-09 17:05:39 +0100959 else if (!strcmp(args[0], "maxcomprate")) {
960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 global.comp_rate_lim = atoi(args[1]) * 1024;
966 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100967 else if (!strcmp(args[0], "maxpipes")) {
968 if (global.maxpipes != 0) {
969 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200970 err_code |= ERR_ALERT;
971 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100972 }
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100977 }
978 global.maxpipes = atol(args[1]);
979 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100980 else if (!strcmp(args[0], "maxzlibmem")) {
981 if (*(args[1]) == 0) {
982 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
William Lallemande3a7d992012-11-20 11:25:20 +0100986 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100987 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100988 else if (!strcmp(args[0], "maxcompcpuusage")) {
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100995 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100996 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000}
1001
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 else if (!strcmp(args[0], "ulimit-n")) {
1003 if (global.rlimit_nofile != 0) {
1004 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT;
1006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 }
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 }
1013 global.rlimit_nofile = atol(args[1]);
1014 }
1015 else if (!strcmp(args[0], "chroot")) {
1016 if (global.chroot != NULL) {
1017 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT;
1019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 }
1026 global.chroot = strdup(args[1]);
1027 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001028 else if (!strcmp(args[0], "description")) {
1029 int i, len=0;
1030 char *d;
1031
1032 if (!*args[1]) {
1033 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1034 file, linenum, args[0]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037 }
1038
Willy Tarreau348acfe2014-04-14 15:00:39 +02001039 for (i = 1; *args[i]; i++)
1040 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001041
1042 if (global.desc)
1043 free(global.desc);
1044
1045 global.desc = d = (char *)calloc(1, len);
1046
Willy Tarreau348acfe2014-04-14 15:00:39 +02001047 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1048 for (i = 2; *args[i]; i++)
1049 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001050 }
1051 else if (!strcmp(args[0], "node")) {
1052 int i;
1053 char c;
1054
1055 for (i=0; args[1][i]; i++) {
1056 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001057 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1058 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001059 break;
1060 }
1061
1062 if (!i || args[1][i]) {
1063 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1064 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1065 file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069
1070 if (global.node)
1071 free(global.node);
1072
1073 global.node = strdup(args[1]);
1074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 else if (!strcmp(args[0], "pidfile")) {
1076 if (global.pidfile != NULL) {
1077 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT;
1079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081 if (*(args[1]) == 0) {
1082 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 }
1086 global.pidfile = strdup(args[1]);
1087 }
Emeric Bruned760922010-10-22 17:59:25 +02001088 else if (!strcmp(args[0], "unix-bind")) {
1089 int cur_arg = 1;
1090 while (*(args[cur_arg])) {
1091 if (!strcmp(args[cur_arg], "prefix")) {
1092 if (global.unix_bind.prefix != NULL) {
1093 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1094 err_code |= ERR_ALERT;
1095 cur_arg += 2;
1096 continue;
1097 }
1098
1099 if (*(args[cur_arg+1]) == 0) {
1100 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
1104 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1105 cur_arg += 2;
1106 continue;
1107 }
1108
1109 if (!strcmp(args[cur_arg], "mode")) {
1110
1111 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1112 cur_arg += 2;
1113 continue;
1114 }
1115
1116 if (!strcmp(args[cur_arg], "uid")) {
1117
1118 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1119 cur_arg += 2;
1120 continue;
1121 }
1122
1123 if (!strcmp(args[cur_arg], "gid")) {
1124
1125 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1126 cur_arg += 2;
1127 continue;
1128 }
1129
1130 if (!strcmp(args[cur_arg], "user")) {
1131 struct passwd *user;
1132
1133 user = getpwnam(args[cur_arg + 1]);
1134 if (!user) {
1135 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1136 file, linenum, args[0], args[cur_arg + 1 ]);
1137 err_code |= ERR_ALERT | ERR_FATAL;
1138 goto out;
1139 }
1140
1141 global.unix_bind.ux.uid = user->pw_uid;
1142 cur_arg += 2;
1143 continue;
1144 }
1145
1146 if (!strcmp(args[cur_arg], "group")) {
1147 struct group *group;
1148
1149 group = getgrnam(args[cur_arg + 1]);
1150 if (!group) {
1151 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1152 file, linenum, args[0], args[cur_arg + 1 ]);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto out;
1155 }
1156
1157 global.unix_bind.ux.gid = group->gr_gid;
1158 cur_arg += 2;
1159 continue;
1160 }
1161
Willy Tarreaub48f9582011-09-05 01:17:06 +02001162 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001163 file, linenum, args[0]);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
1166 }
1167 }
William Lallemand0f99e342011-10-12 17:50:54 +02001168 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1169 /* delete previous herited or defined syslog servers */
1170 struct logsrv *back;
1171 struct logsrv *tmp;
1172
1173 if (*(args[1]) != 0) {
1174 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
1177 }
1178
1179 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1180 LIST_DEL(&tmp->list);
1181 free(tmp);
1182 }
1183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001185 struct sockaddr_storage *sk;
1186 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001187 struct logsrv *logsrv;
1188
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 if (*(args[1]) == 0 || *(args[2]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
William Lallemand0f99e342011-10-12 17:50:54 +02001194
1195 logsrv = calloc(1, sizeof(struct logsrv));
1196
1197 logsrv->facility = get_log_facility(args[2]);
1198 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001201 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203
William Lallemand0f99e342011-10-12 17:50:54 +02001204 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001206 logsrv->level = get_log_level(args[3]);
1207 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001209 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001210 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 }
1212 }
1213
William Lallemand0f99e342011-10-12 17:50:54 +02001214 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001215 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001216 logsrv->minlvl = get_log_level(args[4]);
1217 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001218 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001219 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001220 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001221 }
1222 }
1223
Willy Tarreau902636f2013-03-10 19:44:48 +01001224 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001225 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001226 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001227 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001228 free(logsrv);
1229 goto out;
1230 }
1231 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001232
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001233 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001234 if (port1 != port2) {
1235 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1236 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001237 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001238 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001239 goto out;
1240 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001241
William Lallemand0f99e342011-10-12 17:50:54 +02001242 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001243 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001244 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246
William Lallemand0f99e342011-10-12 17:50:54 +02001247 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001248 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001249 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1250 char *name;
1251 int len;
1252
1253 if (global.log_send_hostname != NULL) {
1254 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1255 err_code |= ERR_ALERT;
1256 goto out;
1257 }
1258
1259 if (*(args[1]))
1260 name = args[1];
1261 else
1262 name = hostname;
1263
1264 len = strlen(name);
1265
1266 /* We'll add a space after the name to respect the log format */
1267 free(global.log_send_hostname);
1268 global.log_send_hostname = malloc(len + 2);
1269 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1270 }
Kevinm48936af2010-12-22 16:08:21 +00001271 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1272 if (*(args[1]) == 0) {
1273 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 free(global.log_tag);
1278 global.log_tag = strdup(args[1]);
1279 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001280 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1281 if (global.spread_checks != 0) {
1282 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001283 err_code |= ERR_ALERT;
1284 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001285 }
1286 if (*(args[1]) == 0) {
1287 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001290 }
1291 global.spread_checks = atol(args[1]);
1292 if (global.spread_checks < 0 || global.spread_checks > 50) {
1293 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001294 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001297 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1298#ifdef USE_CPU_AFFINITY
1299 int cur_arg, i;
1300 unsigned int proc = 0;
1301 unsigned long cpus = 0;
1302
1303 if (strcmp(args[1], "all") == 0)
1304 proc = 0xFFFFFFFF;
1305 else if (strcmp(args[1], "odd") == 0)
1306 proc = 0x55555555;
1307 else if (strcmp(args[1], "even") == 0)
1308 proc = 0xAAAAAAAA;
1309 else {
1310 proc = atoi(args[1]);
1311 if (proc >= 1 && proc <= 32)
1312 proc = 1 << (proc - 1);
1313 }
1314
1315 if (!proc || !*args[2]) {
1316 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1317 file, linenum, args[0]);
1318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
1320 }
1321
1322 cur_arg = 2;
1323 while (*args[cur_arg]) {
1324 unsigned int low, high;
1325
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001326 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001327 char *dash = strchr(args[cur_arg], '-');
1328
1329 low = high = str2uic(args[cur_arg]);
1330 if (dash)
1331 high = str2uic(dash + 1);
1332
1333 if (high < low) {
1334 unsigned int swap = low;
1335 low = high;
1336 high = swap;
1337 }
1338
1339 if (low < 0 || high >= sizeof(long) * 8) {
1340 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1341 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345
1346 while (low <= high)
1347 cpus |= 1UL << low++;
1348 }
1349 else {
1350 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1351 file, linenum, args[0], args[cur_arg]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 cur_arg++;
1356 }
1357 for (i = 0; i < 32; i++)
1358 if (proc & (1 << i))
1359 global.cpu_map[i] = cpus;
1360#else
1361 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364#endif
1365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001367 struct cfg_kw_list *kwl;
1368 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001369 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001370
1371 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1372 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1373 if (kwl->kw[index].section != CFG_GLOBAL)
1374 continue;
1375 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001376 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001377 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001378 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001380 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001381 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001382 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 err_code |= ERR_WARN;
1384 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001385 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001386 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001387 }
1388 }
1389 }
1390
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001394
Willy Tarreau058e9072009-07-20 09:30:05 +02001395 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001396 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001397 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398}
1399
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001400void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001402 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 defproxy.mode = PR_MODE_TCP;
1404 defproxy.state = PR_STNEW;
1405 defproxy.maxconn = cfg_maxpconn;
1406 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001407
Simon Horman66183002013-02-23 10:16:43 +09001408 defproxy.defsrv.check.inter = DEF_CHKINTR;
1409 defproxy.defsrv.check.fastinter = 0;
1410 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001411 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1412 defproxy.defsrv.agent.fastinter = 0;
1413 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001414 defproxy.defsrv.check.rise = DEF_RISETIME;
1415 defproxy.defsrv.check.fall = DEF_FALLTIME;
1416 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1417 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001418 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001419 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001420 defproxy.defsrv.maxqueue = 0;
1421 defproxy.defsrv.minconn = 0;
1422 defproxy.defsrv.maxconn = 0;
1423 defproxy.defsrv.slowstart = 0;
1424 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1425 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1426 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427}
1428
Willy Tarreauade5ec42010-01-28 19:33:49 +01001429
1430static int create_cond_regex_rule(const char *file, int line,
1431 struct proxy *px, int dir, int action, int flags,
1432 const char *cmd, const char *reg, const char *repl,
1433 const char **cond_start)
1434{
1435 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001436 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001437 const char *err;
1438 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001439 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001440
1441 if (px == &defproxy) {
1442 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto err;
1445 }
1446
1447 if (*reg == 0) {
1448 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1449 err_code |= ERR_ALERT | ERR_FATAL;
1450 goto err;
1451 }
1452
1453 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1454 err_code |= ERR_WARN;
1455
Willy Tarreau5321c422010-01-28 20:35:13 +01001456 if (cond_start &&
1457 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001458 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1459 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1460 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto err;
1463 }
1464 }
1465 else if (cond_start && **cond_start) {
1466 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1467 file, line, cmd, *cond_start);
1468 err_code |= ERR_ALERT | ERR_FATAL;
1469 goto err;
1470 }
1471
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001472 err_code |= warnif_cond_conflicts(cond,
1473 (dir == SMP_OPT_DIR_REQ) ?
1474 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1475 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1476 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001477
Willy Tarreauade5ec42010-01-28 19:33:49 +01001478 preg = calloc(1, sizeof(regex_t));
1479 if (!preg) {
1480 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1481 err_code = ERR_ALERT | ERR_FATAL;
1482 goto err;
1483 }
1484
1485 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1486 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1487 err_code = ERR_ALERT | ERR_FATAL;
1488 goto err;
1489 }
1490
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001491 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001492 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001493 if (repl && err) {
1494 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1495 file, line, cmd, *err);
1496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto err;
1498 }
1499
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001500 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001501 err_code |= ERR_WARN;
1502
Willy Tarreauf4068b62012-05-08 17:37:49 +02001503 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001504 return err_code;
1505 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001506 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001507 free(preg);
1508 return err_code;
1509}
1510
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001513 * Returns the error code, 0 if OK, or any combination of :
1514 * - ERR_ABORT: must abort ASAP
1515 * - ERR_FATAL: we can continue parsing but not start the service
1516 * - ERR_WARN: a warning has been emitted
1517 * - ERR_ALERT: an alert has been emitted
1518 * Only the two first ones can stop processing, the two others are just
1519 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001521int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1522{
1523 static struct peers *curpeers = NULL;
1524 struct peer *newpeer = NULL;
1525 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001526 struct bind_conf *bind_conf;
1527 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001528 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001529 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001530
1531 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001532 if (!*args[1]) {
1533 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001534 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001535 goto out;
1536 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001537
1538 err = invalid_char(args[1]);
1539 if (err) {
1540 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1541 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001542 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001543 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 }
1545
1546 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1547 /*
1548 * If there are two proxies with the same name only following
1549 * combinations are allowed:
1550 */
1551 if (strcmp(curpeers->id, args[1]) == 0) {
1552 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1553 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1554 err_code |= ERR_WARN;
1555 }
1556 }
1557
1558 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
1563
1564 curpeers->next = peers;
1565 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001566 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001567 curpeers->conf.line = linenum;
1568 curpeers->last_change = now.tv_sec;
1569 curpeers->id = strdup(args[1]);
1570 }
1571 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001572 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001573 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001574 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001575
1576 if (!*args[2]) {
1577 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1578 file, linenum, args[0]);
1579 err_code |= ERR_ALERT | ERR_FATAL;
1580 goto out;
1581 }
1582
1583 err = invalid_char(args[1]);
1584 if (err) {
1585 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1586 file, linenum, *err, args[1]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
1591 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1592 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1593 err_code |= ERR_ALERT | ERR_ABORT;
1594 goto out;
1595 }
1596
1597 /* the peers are linked backwards first */
1598 curpeers->count++;
1599 newpeer->next = curpeers->remote;
1600 curpeers->remote = newpeer;
1601 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001602 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001603 newpeer->conf.line = linenum;
1604
1605 newpeer->last_change = now.tv_sec;
1606 newpeer->id = strdup(args[1]);
1607
Willy Tarreau902636f2013-03-10 19:44:48 +01001608 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001609 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001610 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001611 err_code |= ERR_ALERT | ERR_FATAL;
1612 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001613 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001614
1615 proto = protocol_by_family(sk->ss_family);
1616 if (!proto || !proto->connect) {
1617 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1618 file, linenum, args[0], args[1]);
1619 err_code |= ERR_ALERT | ERR_FATAL;
1620 goto out;
1621 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001622
1623 if (port1 != port2) {
1624 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1625 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
1629
Willy Tarreau2aa38802013-02-20 19:20:59 +01001630 if (!port1) {
1631 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1632 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001633 err_code |= ERR_ALERT | ERR_FATAL;
1634 goto out;
1635 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001636
Emeric Brun32da3c42010-09-23 18:39:19 +02001637 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001638 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001639 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001640 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001641
Emeric Brun32da3c42010-09-23 18:39:19 +02001642 if (strcmp(newpeer->id, localpeer) == 0) {
1643 /* Current is local peer, it define a frontend */
1644 newpeer->local = 1;
1645
1646 if (!curpeers->peers_fe) {
1647 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1648 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1649 err_code |= ERR_ALERT | ERR_ABORT;
1650 goto out;
1651 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001652
Willy Tarreau237250c2011-07-29 01:49:03 +02001653 init_new_proxy(curpeers->peers_fe);
1654 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001655
1656 curpeers->peers_fe->last_change = now.tv_sec;
1657 curpeers->peers_fe->id = strdup(args[1]);
1658 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001659 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001660 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1661 curpeers->peers_fe->timeout.connect = 5000;
1662 curpeers->peers_fe->accept = peer_accept;
1663 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001664 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1665 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001666
1667 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1668
Willy Tarreau902636f2013-03-10 19:44:48 +01001669 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1670 if (errmsg && *errmsg) {
1671 indent_msg(&errmsg, 2);
1672 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001673 }
1674 else
1675 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1676 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001677 err_code |= ERR_FATAL;
1678 goto out;
1679 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001680
1681 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1682 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1683 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1684 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1685 l->accept = session_accept;
1686 l->handler = process_session;
1687 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1688 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1689 global.maxsock += l->maxconn;
1690 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001691 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001692 else {
1693 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1694 file, linenum, args[0], args[1],
1695 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1696 err_code |= ERR_FATAL;
1697 goto out;
1698 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001699 }
1700 } /* neither "peer" nor "peers" */
1701 else if (*args[0] != 0) {
1702 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
1705 }
1706
1707out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001708 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001709 return err_code;
1710}
1711
Willy Tarreau3842f002009-06-14 11:39:52 +02001712int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713{
1714 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001715 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001716 int rc;
1717 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001718 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001719 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001720 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001721 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001722 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723
Willy Tarreau977b8e42006-12-29 14:19:17 +01001724 if (!strcmp(args[0], "listen"))
1725 rc = PR_CAP_LISTEN;
1726 else if (!strcmp(args[0], "frontend"))
1727 rc = PR_CAP_FE | PR_CAP_RS;
1728 else if (!strcmp(args[0], "backend"))
1729 rc = PR_CAP_BE | PR_CAP_RS;
1730 else if (!strcmp(args[0], "ruleset"))
1731 rc = PR_CAP_RS;
1732 else
1733 rc = PR_CAP_NONE;
1734
1735 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001736 struct ebpt_node *node;
1737
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738 if (!*args[1]) {
1739 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1740 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1741 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_ABORT;
1743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001745
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001746 err = invalid_char(args[1]);
1747 if (err) {
1748 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1749 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001751 }
1752
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001753 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1754 curproxy = container_of(node, struct proxy, conf.by_name);
1755
1756 if (strcmp(curproxy->id, args[1]) != 0)
1757 break;
1758
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001759 /*
1760 * If there are two proxies with the same name only following
1761 * combinations are allowed:
1762 *
1763 * listen backend frontend ruleset
1764 * listen - - - -
1765 * backend - - OK -
1766 * frontend - OK - -
1767 * ruleset - - - -
1768 */
1769
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001770 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1771 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001772 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1773 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1774 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001775 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001776 }
1777 }
1778
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1780 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001781 err_code |= ERR_ALERT | ERR_ABORT;
1782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001784
Willy Tarreau97cb7802010-01-03 20:23:58 +01001785 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 curproxy->next = proxy;
1787 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001788 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1789 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001790 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001793 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794
1795 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001796 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001797 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001798
Willy Tarreau4348fad2012-09-20 16:48:07 +02001799 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1800
Willy Tarreau902636f2013-03-10 19:44:48 +01001801 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1802 if (errmsg && *errmsg) {
1803 indent_msg(&errmsg, 2);
1804 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001805 }
1806 else
1807 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1808 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_FATAL;
1810 goto out;
1811 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001812
Willy Tarreau4348fad2012-09-20 16:48:07 +02001813 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001814 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 }
1817
1818 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001819 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001820 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001821
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001824 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001825 curproxy->no_options = defproxy.no_options;
1826 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001827 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001828 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001829 curproxy->except_net = defproxy.except_net;
1830 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001831 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001832 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001834 if (defproxy.fwdfor_hdr_len) {
1835 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1836 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1837 }
1838
Willy Tarreaub86db342009-11-30 11:50:16 +01001839 if (defproxy.orgto_hdr_len) {
1840 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1841 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1842 }
1843
Mark Lamourinec2247f02012-01-04 13:02:01 -05001844 if (defproxy.server_id_hdr_len) {
1845 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1846 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1847 }
1848
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 if (curproxy->cap & PR_CAP_FE) {
1850 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001851 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001852 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853
1854 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001855 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1856 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857
1858 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 if (curproxy->cap & PR_CAP_BE) {
1862 curproxy->fullconn = defproxy.fullconn;
1863 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001865 if (defproxy.check_req) {
1866 curproxy->check_req = calloc(1, defproxy.check_len);
1867 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1868 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001869 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001871 if (defproxy.expect_str) {
1872 curproxy->expect_str = strdup(defproxy.expect_str);
1873 if (defproxy.expect_regex) {
1874 /* note: this regex is known to be valid */
1875 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1876 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1877 }
1878 }
1879
Willy Tarreau67402132012-05-31 20:40:20 +02001880 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001881 if (defproxy.cookie_name)
1882 curproxy->cookie_name = strdup(defproxy.cookie_name);
1883 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001884 if (defproxy.cookie_domain)
1885 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001886
Willy Tarreau31936852010-10-06 16:59:56 +02001887 if (defproxy.cookie_maxidle)
1888 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1889
1890 if (defproxy.cookie_maxlife)
1891 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1892
Emeric Brun647caf12009-06-30 17:57:00 +02001893 if (defproxy.rdp_cookie_name)
1894 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1895 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1896
Willy Tarreau01732802007-11-01 22:48:15 +01001897 if (defproxy.url_param_name)
1898 curproxy->url_param_name = strdup(defproxy.url_param_name);
1899 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001900
Benoitaffb4812009-03-25 13:02:10 +01001901 if (defproxy.hh_name)
1902 curproxy->hh_name = strdup(defproxy.hh_name);
1903 curproxy->hh_len = defproxy.hh_len;
1904 curproxy->hh_match_domain = defproxy.hh_match_domain;
1905
Willy Tarreauef9a3602012-12-08 22:29:20 +01001906 if (defproxy.conn_src.iface_name)
1907 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1908 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001909 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001910#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001911 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001912#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001915 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (defproxy.capture_name)
1917 curproxy->capture_name = strdup(defproxy.capture_name);
1918 curproxy->capture_namelen = defproxy.capture_namelen;
1919 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001923 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001924 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001925 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001926 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001927 curproxy->uri_auth = defproxy.uri_auth;
1928 curproxy->mon_net = defproxy.mon_net;
1929 curproxy->mon_mask = defproxy.mon_mask;
1930 if (defproxy.monitor_uri)
1931 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1932 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001933 if (defproxy.defbe.name)
1934 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001935
1936 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001937 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1938 if (curproxy->conf.logformat_string &&
1939 curproxy->conf.logformat_string != default_http_log_format &&
1940 curproxy->conf.logformat_string != default_tcp_log_format &&
1941 curproxy->conf.logformat_string != clf_http_log_format)
1942 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1943
1944 if (defproxy.conf.lfs_file) {
1945 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1946 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1947 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001948 }
1949
1950 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001951 curproxy->timeout.connect = defproxy.timeout.connect;
1952 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001953 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001954 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001955 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001956 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001957 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001958 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001959 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001960 }
1961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001963
1964 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001965 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001966 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001967 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001968 LIST_INIT(&node->list);
1969 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1970 }
1971
Willy Tarreau62a61232013-04-12 18:13:46 +02001972 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1973 if (curproxy->conf.uniqueid_format_string)
1974 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1975
1976 if (defproxy.conf.uif_file) {
1977 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1978 curproxy->conf.uif_line = defproxy.conf.uif_line;
1979 }
William Lallemanda73203e2012-03-12 12:48:57 +01001980
1981 /* copy default header unique id */
1982 if (defproxy.header_unique_id)
1983 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1984
William Lallemand82fe75c2012-10-23 10:25:10 +02001985 /* default compression options */
1986 if (defproxy.comp != NULL) {
1987 curproxy->comp = calloc(1, sizeof(struct comp));
1988 curproxy->comp->algos = defproxy.comp->algos;
1989 curproxy->comp->types = defproxy.comp->types;
1990 }
1991
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001993 curproxy->conf.used_listener_id = EB_ROOT;
1994 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001995
Willy Tarreau93893792009-07-23 13:19:11 +02001996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 }
1998 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1999 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002000 /* FIXME-20070101: we should do this too at the end of the
2001 * config parsing to free all default values.
2002 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002003 free(defproxy.check_req);
2004 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002005 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002006 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002007 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002008 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002009 free(defproxy.capture_name);
2010 free(defproxy.monitor_uri);
2011 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002012 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002013 free(defproxy.fwdfor_hdr_name);
2014 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002015 free(defproxy.orgto_hdr_name);
2016 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002017 free(defproxy.server_id_hdr_name);
2018 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002019 free(defproxy.expect_str);
2020 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002021
Willy Tarreau62a61232013-04-12 18:13:46 +02002022 if (defproxy.conf.logformat_string != default_http_log_format &&
2023 defproxy.conf.logformat_string != default_tcp_log_format &&
2024 defproxy.conf.logformat_string != clf_http_log_format)
2025 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002026
Willy Tarreau62a61232013-04-12 18:13:46 +02002027 free(defproxy.conf.uniqueid_format_string);
2028 free(defproxy.conf.lfs_file);
2029 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002030
Willy Tarreaua534fea2008-08-03 12:19:50 +02002031 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002032 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002033
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 /* we cannot free uri_auth because it might already be used */
2035 init_default_instance();
2036 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002037 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2038 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
2042 else if (curproxy == NULL) {
2043 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002047
2048 /* update the current file and line being parsed */
2049 curproxy->conf.args.file = curproxy->conf.file;
2050 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002051
2052 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002053 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2054 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2055 if (err_code & ERR_FATAL)
2056 goto out;
2057 }
2058 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002059 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002060 int cur_arg;
2061
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 if (curproxy == &defproxy) {
2063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002067 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069
Willy Tarreau24709282013-03-10 21:32:12 +01002070 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002071 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002076
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002077 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002078
2079 /* use default settings for unix sockets */
2080 bind_conf->ux.uid = global.unix_bind.ux.uid;
2081 bind_conf->ux.gid = global.unix_bind.ux.gid;
2082 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002083
2084 /* NOTE: the following line might create several listeners if there
2085 * are comma-separated IPs or port ranges. So all further processing
2086 * will have to be applied to all listeners created after last_listen.
2087 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002088 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2089 if (errmsg && *errmsg) {
2090 indent_msg(&errmsg, 2);
2091 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002092 }
2093 else
2094 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2095 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
2098 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002099
Willy Tarreau4348fad2012-09-20 16:48:07 +02002100 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2101 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002102 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002103 }
2104
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002105 cur_arg = 2;
2106 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002107 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002108 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002109 char *err;
2110
Willy Tarreau26982662012-09-12 23:17:10 +02002111 kw = bind_find_kw(args[cur_arg]);
2112 if (kw) {
2113 char *err = NULL;
2114 int code;
2115
2116 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002117 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2118 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002119 cur_arg += 1 + kw->skip ;
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
2123
Willy Tarreau4348fad2012-09-20 16:48:07 +02002124 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002125 err_code |= code;
2126
2127 if (code) {
2128 if (err && *err) {
2129 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002130 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002131 }
2132 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002133 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2134 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002135 if (code & ERR_FATAL) {
2136 free(err);
2137 cur_arg += 1 + kw->skip;
2138 goto out;
2139 }
2140 }
2141 free(err);
2142 cur_arg += 1 + kw->skip;
2143 continue;
2144 }
2145
Willy Tarreau8638f482012-09-18 18:01:17 +02002146 err = NULL;
2147 if (!bind_dumped) {
2148 bind_dump_kws(&err);
2149 indent_msg(&err, 4);
2150 bind_dumped = 1;
2151 }
2152
2153 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2154 file, linenum, args[0], args[1], args[cur_arg],
2155 err ? " Registered keywords :" : "", err ? err : "");
2156 free(err);
2157
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002160 }
Willy Tarreau93893792009-07-23 13:19:11 +02002161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 }
2163 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002164 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2166 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002169 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002170 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002171 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002172
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 /* flush useless bits */
2174 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002177 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002178 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002179 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002180
Willy Tarreau1c47f852006-07-09 08:22:27 +02002181 if (!*args[1]) {
2182 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2183 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002186 }
2187
Willy Tarreaua534fea2008-08-03 12:19:50 +02002188 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002189 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002190 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002191 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002192 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2193
Willy Tarreau93893792009-07-23 13:19:11 +02002194 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2197 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2198 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2199 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2200 else {
2201 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 }
2205 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002206 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002207 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002208
2209 if (curproxy == &defproxy) {
2210 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2211 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002214 }
2215
2216 if (!*args[1]) {
2217 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2218 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002221 }
2222
2223 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002224 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002225
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002226 if (curproxy->uuid <= 0) {
2227 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002228 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002231 }
2232
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002233 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2234 if (node) {
2235 struct proxy *target = container_of(node, struct proxy, conf.id);
2236 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2237 file, linenum, proxy_type_str(curproxy), curproxy->id,
2238 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002243 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002244 else if (!strcmp(args[0], "description")) {
2245 int i, len=0;
2246 char *d;
2247
Cyril Bonté99ed3272010-01-24 23:29:44 +01002248 if (curproxy == &defproxy) {
2249 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2250 file, linenum, args[0]);
2251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002255 if (!*args[1]) {
2256 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2257 file, linenum, args[0]);
2258 return -1;
2259 }
2260
Willy Tarreau348acfe2014-04-14 15:00:39 +02002261 for (i = 1; *args[i]; i++)
2262 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002263
2264 d = (char *)calloc(1, len);
2265 curproxy->desc = d;
2266
Willy Tarreau348acfe2014-04-14 15:00:39 +02002267 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2268 for (i = 2; *args[i]; i++)
2269 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002270
2271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2273 curproxy->state = PR_STSTOPPED;
2274 }
2275 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2276 curproxy->state = PR_STNEW;
2277 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002278 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2279 int cur_arg = 1;
2280 unsigned int set = 0;
2281
2282 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002283 unsigned int low, high;
2284
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002285 if (strcmp(args[cur_arg], "all") == 0) {
2286 set = 0;
2287 break;
2288 }
2289 else if (strcmp(args[cur_arg], "odd") == 0) {
2290 set |= 0x55555555;
2291 }
2292 else if (strcmp(args[cur_arg], "even") == 0) {
2293 set |= 0xAAAAAAAA;
2294 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002295 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002296 char *dash = strchr(args[cur_arg], '-');
2297
2298 low = high = str2uic(args[cur_arg]);
2299 if (dash)
2300 high = str2uic(dash + 1);
2301
2302 if (high < low) {
2303 unsigned int swap = low;
2304 low = high;
2305 high = swap;
2306 }
2307
2308 if (low < 1 || high > 32) {
2309 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002313 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002314
2315 if (high > global.nbproc) {
2316 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2317 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002319 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002320 while (low <= high)
2321 set |= 1 << (low++ - 1);
2322 }
2323 else {
2324 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2325 file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002328 }
2329 cur_arg++;
2330 }
2331 curproxy->bind_proc = set;
2332 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002333 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002334 if (curproxy == &defproxy) {
2335 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002338 }
2339
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002340 err = invalid_char(args[1]);
2341 if (err) {
2342 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2343 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002345 }
2346
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002347 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002348 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2349 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002352 }
2353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2355 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 if (*(args[1]) == 0) {
2361 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2362 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002366
Willy Tarreau67402132012-05-31 20:40:20 +02002367 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002368 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002369 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002370 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 curproxy->cookie_name = strdup(args[1]);
2372 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002373
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 cur_arg = 2;
2375 while (*(args[cur_arg])) {
2376 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002377 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002380 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
2382 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002383 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002386 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
2388 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002389 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002391 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002392 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002395 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002397 else if (!strcmp(args[cur_arg], "httponly")) {
2398 curproxy->ck_opts |= PR_CK_HTTPONLY;
2399 }
2400 else if (!strcmp(args[cur_arg], "secure")) {
2401 curproxy->ck_opts |= PR_CK_SECURE;
2402 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002403 else if (!strcmp(args[cur_arg], "domain")) {
2404 if (!*args[cur_arg + 1]) {
2405 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2406 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002409 }
2410
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002411 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002412 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002413 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2414 " dots nor does not start with a dot."
2415 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002416 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002417 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002418 }
2419
2420 err = invalid_domainchar(args[cur_arg + 1]);
2421 if (err) {
2422 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2423 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002426 }
2427
Willy Tarreau68a897b2009-12-03 23:28:34 +01002428 if (!curproxy->cookie_domain) {
2429 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2430 } else {
2431 /* one domain was already specified, add another one by
2432 * building the string which will be returned along with
2433 * the cookie.
2434 */
2435 char *new_ptr;
2436 int new_len = strlen(curproxy->cookie_domain) +
2437 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2438 new_ptr = malloc(new_len);
2439 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2440 free(curproxy->cookie_domain);
2441 curproxy->cookie_domain = new_ptr;
2442 }
Willy Tarreau31936852010-10-06 16:59:56 +02002443 cur_arg++;
2444 }
2445 else if (!strcmp(args[cur_arg], "maxidle")) {
2446 unsigned int maxidle;
2447 const char *res;
2448
2449 if (!*args[cur_arg + 1]) {
2450 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2451 file, linenum, args[cur_arg]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2457 if (res) {
2458 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2459 file, linenum, *res, args[cur_arg]);
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
2462 }
2463 curproxy->cookie_maxidle = maxidle;
2464 cur_arg++;
2465 }
2466 else if (!strcmp(args[cur_arg], "maxlife")) {
2467 unsigned int maxlife;
2468 const char *res;
2469
2470 if (!*args[cur_arg + 1]) {
2471 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2472 file, linenum, args[cur_arg]);
2473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
2475 }
2476
2477 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2478 if (res) {
2479 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2480 file, linenum, *res, args[cur_arg]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002485 cur_arg++;
2486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002488 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 +02002489 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 }
2493 cur_arg++;
2494 }
Willy Tarreau67402132012-05-31 20:40:20 +02002495 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2497 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 }
2500
Willy Tarreau67402132012-05-31 20:40:20 +02002501 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2503 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002506
Willy Tarreau67402132012-05-31 20:40:20 +02002507 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002508 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2509 file, linenum);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002513 else if (!strcmp(args[0], "persist")) { /* persist */
2514 if (*(args[1]) == 0) {
2515 Alert("parsing [%s:%d] : missing persist method.\n",
2516 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002519 }
2520
2521 if (!strncmp(args[1], "rdp-cookie", 10)) {
2522 curproxy->options2 |= PR_O2_RDPC_PRST;
2523
Emeric Brunb982a3d2010-01-04 15:45:53 +01002524 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002525 const char *beg, *end;
2526
2527 beg = args[1] + 11;
2528 end = strchr(beg, ')');
2529
2530 if (!end || end == beg) {
2531 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2532 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002535 }
2536
2537 free(curproxy->rdp_cookie_name);
2538 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2539 curproxy->rdp_cookie_len = end-beg;
2540 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002541 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002542 free(curproxy->rdp_cookie_name);
2543 curproxy->rdp_cookie_name = strdup("msts");
2544 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2545 }
2546 else { /* syntax */
2547 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2548 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002551 }
2552 }
2553 else {
2554 Alert("parsing [%s:%d] : unknown persist method.\n",
2555 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002558 }
2559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002561 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002563 if (curproxy == &defproxy) {
2564 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
2567 }
2568
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002573 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
2578 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002579 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 curproxy->appsession_name = strdup(args[1]);
2581 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2582 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002583 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2584 if (err) {
2585 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2586 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002589 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002590 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002591
Willy Tarreau51041c72007-09-09 21:56:53 +02002592 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2593 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_ABORT;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002597
2598 cur_arg = 6;
2599 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002600 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2601 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002602 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002603 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002604 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002605 } else if (!strcmp(args[cur_arg], "prefix")) {
2606 curproxy->options2 |= PR_O2_AS_PFX;
2607 } else if (!strcmp(args[cur_arg], "mode")) {
2608 if (!*args[cur_arg + 1]) {
2609 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2610 file, linenum, args[0], args[cur_arg]);
2611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
2613 }
2614
2615 cur_arg++;
2616 if (!strcmp(args[cur_arg], "query-string")) {
2617 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2618 curproxy->options2 |= PR_O2_AS_M_QS;
2619 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2620 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2621 curproxy->options2 |= PR_O2_AS_M_PP;
2622 } else {
2623 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002628 cur_arg++;
2629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 } /* Url App Session */
2631 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002632 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002634
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002636 if (curproxy == &defproxy) {
2637 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
2641
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 if (*(args[4]) == 0) {
2643 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002648 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 curproxy->capture_name = strdup(args[2]);
2650 curproxy->capture_namelen = strlen(curproxy->capture_name);
2651 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 curproxy->to_log |= LW_COOKIE;
2653 }
2654 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2655 struct cap_hdr *hdr;
2656
2657 if (curproxy == &defproxy) {
2658 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 +02002659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 }
2662
2663 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2664 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2665 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 }
2669
2670 hdr = calloc(sizeof(struct cap_hdr), 1);
2671 hdr->next = curproxy->req_cap;
2672 hdr->name = strdup(args[3]);
2673 hdr->namelen = strlen(args[3]);
2674 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002675 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 hdr->index = curproxy->nb_req_cap++;
2677 curproxy->req_cap = hdr;
2678 curproxy->to_log |= LW_REQHDR;
2679 }
2680 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2681 struct cap_hdr *hdr;
2682
2683 if (curproxy == &defproxy) {
2684 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 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 }
2688
2689 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2690 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2691 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 }
2695 hdr = calloc(sizeof(struct cap_hdr), 1);
2696 hdr->next = curproxy->rsp_cap;
2697 hdr->name = strdup(args[3]);
2698 hdr->namelen = strlen(args[3]);
2699 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002700 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 hdr->index = curproxy->nb_rsp_cap++;
2702 curproxy->rsp_cap = hdr;
2703 curproxy->to_log |= LW_RSPHDR;
2704 }
2705 else {
2706 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 }
2711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002713 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 if (*(args[1]) == 0) {
2717 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 }
2722 curproxy->conn_retries = atol(args[1]);
2723 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002724 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002725 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002726
2727 if (curproxy == &defproxy) {
2728 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
2731 }
2732
Willy Tarreau20b0de52012-12-24 15:45:22 +01002733 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2734 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2735 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2736 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002737 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002738 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2739 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 +01002740 file, linenum, args[0]);
2741 err_code |= ERR_WARN;
2742 }
2743
Willy Tarreauff011f22011-01-06 17:51:27 +01002744 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002745
Willy Tarreauff011f22011-01-06 17:51:27 +01002746 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002747 err_code |= ERR_ALERT | ERR_ABORT;
2748 goto out;
2749 }
2750
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002751 err_code |= warnif_cond_conflicts(rule->cond,
2752 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2753 file, linenum);
2754
Willy Tarreauff011f22011-01-06 17:51:27 +01002755 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002756 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002757 else if (!strcmp(args[0], "http-response")) { /* response access control */
2758 struct http_res_rule *rule;
2759
2760 if (curproxy == &defproxy) {
2761 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
2766 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2767 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2768 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2769 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2770 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2771 file, linenum, args[0]);
2772 err_code |= ERR_WARN;
2773 }
2774
2775 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2776
2777 if (!rule) {
2778 err_code |= ERR_ALERT | ERR_ABORT;
2779 goto out;
2780 }
2781
2782 err_code |= warnif_cond_conflicts(rule->cond,
2783 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2784 file, linenum);
2785
2786 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2787 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002788 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2789 /* set the header name and length into the proxy structure */
2790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2791 err_code |= ERR_WARN;
2792
2793 if (!*args[1]) {
2794 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2795 file, linenum, args[0]);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
2799
2800 /* set the desired header name */
2801 free(curproxy->server_id_hdr_name);
2802 curproxy->server_id_hdr_name = strdup(args[1]);
2803 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2804 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002805 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002806 if (curproxy == &defproxy) {
2807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002810 }
2811
Willy Tarreauef6494c2010-01-28 17:12:36 +01002812 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002813 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2814 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002817 }
2818
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002819 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2820 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2821 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002824 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002825
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002826 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002827 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002828 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002829 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002830 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002831
Cyril Bonté99ed3272010-01-24 23:29:44 +01002832 if (curproxy == &defproxy) {
2833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002838 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002839 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2840 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002843 }
2844
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002845 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002846 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002847 err_code |= warnif_cond_conflicts(rule->cond,
2848 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2849 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002850 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002851 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002852 struct switching_rule *rule;
2853
Willy Tarreaub099aca2008-10-12 17:26:37 +02002854 if (curproxy == &defproxy) {
2855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002858 }
2859
Willy Tarreau55ea7572007-06-17 19:56:27 +02002860 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002862
2863 if (*(args[1]) == 0) {
2864 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002867 }
2868
Willy Tarreauef6494c2010-01-28 17:12:36 +01002869 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002870 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2871 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002874 }
2875
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002876 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2877 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2878 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002881 }
2882
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002883 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002884
Willy Tarreau55ea7572007-06-17 19:56:27 +02002885 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2886 rule->cond = cond;
2887 rule->be.name = strdup(args[1]);
2888 LIST_INIT(&rule->list);
2889 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2890 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002891 else if (strcmp(args[0], "use-server") == 0) {
2892 struct server_rule *rule;
2893
2894 if (curproxy == &defproxy) {
2895 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899
2900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2901 err_code |= ERR_WARN;
2902
2903 if (*(args[1]) == 0) {
2904 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908
2909 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2910 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2911 file, linenum, args[0]);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002916 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2917 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2918 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921 }
2922
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002923 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002924
2925 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2926 rule->cond = cond;
2927 rule->srv.name = strdup(args[1]);
2928 LIST_INIT(&rule->list);
2929 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2930 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2931 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002932 else if ((!strcmp(args[0], "force-persist")) ||
2933 (!strcmp(args[0], "ignore-persist"))) {
2934 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002935
2936 if (curproxy == &defproxy) {
2937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940 }
2941
2942 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2943 err_code |= ERR_WARN;
2944
Willy Tarreauef6494c2010-01-28 17:12:36 +01002945 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002946 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2947 file, linenum, args[0]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002952 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2953 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2954 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002959 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2960 * where force-persist is applied.
2961 */
2962 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002963
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002964 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002965 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002966 if (!strcmp(args[0], "force-persist")) {
2967 rule->type = PERSIST_TYPE_FORCE;
2968 } else {
2969 rule->type = PERSIST_TYPE_IGNORE;
2970 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002971 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002972 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002973 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002974 else if (!strcmp(args[0], "stick-table")) {
2975 int myidx = 1;
2976
Emeric Brun32da3c42010-09-23 18:39:19 +02002977 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002978 curproxy->table.type = (unsigned int)-1;
2979 while (*args[myidx]) {
2980 const char *err;
2981
2982 if (strcmp(args[myidx], "size") == 0) {
2983 myidx++;
2984 if (!*(args[myidx])) {
2985 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2986 file, linenum, args[myidx-1]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2991 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2992 file, linenum, *err, args[myidx-1]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002996 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002997 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002998 else if (strcmp(args[myidx], "peers") == 0) {
2999 myidx++;
Godbach50523162013-12-11 19:48:57 +08003000 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003001 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3002 file, linenum, args[myidx-1]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Godbach50523162013-12-11 19:48:57 +08003005 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003006 curproxy->table.peers.name = strdup(args[myidx++]);
3007 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003008 else if (strcmp(args[myidx], "expire") == 0) {
3009 myidx++;
3010 if (!*(args[myidx])) {
3011 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3012 file, linenum, args[myidx-1]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3017 if (err) {
3018 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3019 file, linenum, *err, args[myidx-1]);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003024 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003025 }
3026 else if (strcmp(args[myidx], "nopurge") == 0) {
3027 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003028 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003029 }
3030 else if (strcmp(args[myidx], "type") == 0) {
3031 myidx++;
3032 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3033 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3034 file, linenum, args[myidx]);
3035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
3037 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003038 /* myidx already points to next arg */
3039 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003040 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003041 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003042 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003043
3044 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003045 nw = args[myidx];
3046 while (*nw) {
3047 /* the "store" keyword supports a comma-separated list */
3048 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003049 sa = NULL; /* store arg */
3050 while (*nw && *nw != ',') {
3051 if (*nw == '(') {
3052 *nw = 0;
3053 sa = ++nw;
3054 while (*nw != ')') {
3055 if (!*nw) {
3056 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3057 file, linenum, args[0], cw);
3058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
3060 }
3061 nw++;
3062 }
3063 *nw = '\0';
3064 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003065 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003066 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003067 if (*nw)
3068 *nw++ = '\0';
3069 type = stktable_get_data_type(cw);
3070 if (type < 0) {
3071 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3072 file, linenum, args[0], cw);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
3075 }
Willy Tarreauac782882010-06-20 10:41:54 +02003076
3077 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3078 switch (err) {
3079 case PE_NONE: break;
3080 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003081 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3082 file, linenum, args[0], cw);
3083 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003084 break;
3085
3086 case PE_ARG_MISSING:
3087 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3088 file, linenum, args[0], cw);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091
3092 case PE_ARG_NOT_USED:
3093 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3094 file, linenum, args[0], cw);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097
3098 default:
3099 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3100 file, linenum, args[0], cw);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003103 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003104 }
3105 myidx++;
3106 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003107 else {
3108 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3109 file, linenum, args[myidx]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003112 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003113 }
3114
3115 if (!curproxy->table.size) {
3116 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3117 file, linenum);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121
3122 if (curproxy->table.type == (unsigned int)-1) {
3123 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3124 file, linenum);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128 }
3129 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003130 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003131 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003132 int myidx = 0;
3133 const char *name = NULL;
3134 int flags;
3135
3136 if (curproxy == &defproxy) {
3137 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
3140 }
3141
3142 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3143 err_code |= ERR_WARN;
3144 goto out;
3145 }
3146
3147 myidx++;
3148 if ((strcmp(args[myidx], "store") == 0) ||
3149 (strcmp(args[myidx], "store-request") == 0)) {
3150 myidx++;
3151 flags = STK_IS_STORE;
3152 }
3153 else if (strcmp(args[myidx], "store-response") == 0) {
3154 myidx++;
3155 flags = STK_IS_STORE | STK_ON_RSP;
3156 }
3157 else if (strcmp(args[myidx], "match") == 0) {
3158 myidx++;
3159 flags = STK_IS_MATCH;
3160 }
3161 else if (strcmp(args[myidx], "on") == 0) {
3162 myidx++;
3163 flags = STK_IS_MATCH | STK_IS_STORE;
3164 }
3165 else {
3166 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170
3171 if (*(args[myidx]) == 0) {
3172 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003177 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003178 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003179 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003180 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
3183 }
3184
3185 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003186 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3187 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3188 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003189 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003190 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003191 goto out;
3192 }
3193 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003194 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3195 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3196 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003197 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003198 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003199 goto out;
3200 }
3201 }
3202
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003203 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003204 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003205
Emeric Brunb982a3d2010-01-04 15:45:53 +01003206 if (strcmp(args[myidx], "table") == 0) {
3207 myidx++;
3208 name = args[myidx++];
3209 }
3210
Willy Tarreauef6494c2010-01-28 17:12:36 +01003211 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003212 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3213 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3214 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003215 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003216 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003217 goto out;
3218 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003219 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003220 else if (*(args[myidx])) {
3221 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3222 file, linenum, args[0], args[myidx]);
3223 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003224 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003225 goto out;
3226 }
Emeric Brun97679e72010-09-23 17:56:44 +02003227 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003228 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003229 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003230 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003231
Emeric Brunb982a3d2010-01-04 15:45:53 +01003232 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3233 rule->cond = cond;
3234 rule->expr = expr;
3235 rule->flags = flags;
3236 rule->table.name = name ? strdup(name) : NULL;
3237 LIST_INIT(&rule->list);
3238 if (flags & STK_ON_RSP)
3239 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3240 else
3241 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003244 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003246
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3248 curproxy->uri_auth = NULL; /* we must detach from the default config */
3249
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003250 if (!*args[1]) {
3251 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003252 } else if (!strcmp(args[1], "admin")) {
3253 struct stats_admin_rule *rule;
3254
3255 if (curproxy == &defproxy) {
3256 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260
3261 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3262 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3263 err_code |= ERR_ALERT | ERR_ABORT;
3264 goto out;
3265 }
3266
3267 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3268 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3269 file, linenum, args[0], args[1]);
3270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
3272 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003273 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3274 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3275 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278 }
3279
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003280 err_code |= warnif_cond_conflicts(cond,
3281 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3282 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003283
3284 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3285 rule->cond = cond;
3286 LIST_INIT(&rule->list);
3287 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 } else if (!strcmp(args[1], "uri")) {
3289 if (*(args[2]) == 0) {
3290 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003291 err_code |= ERR_ALERT | ERR_FATAL;
3292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3294 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_ABORT;
3296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 }
3298 } else if (!strcmp(args[1], "realm")) {
3299 if (*(args[2]) == 0) {
3300 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3304 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_ABORT;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003308 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003309 unsigned interval;
3310
3311 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3312 if (err) {
3313 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3314 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003317 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3318 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_ALERT | ERR_ABORT;
3320 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003321 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003322 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003323 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003324
3325 if (curproxy == &defproxy) {
3326 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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
Willy Tarreauff011f22011-01-06 17:51:27 +01003337 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3338 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003339 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3340 file, linenum, args[0]);
3341 err_code |= ERR_WARN;
3342 }
3343
Willy Tarreauff011f22011-01-06 17:51:27 +01003344 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003345
Willy Tarreauff011f22011-01-06 17:51:27 +01003346 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003347 err_code |= ERR_ALERT | ERR_ABORT;
3348 goto out;
3349 }
3350
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003351 err_code |= warnif_cond_conflicts(rule->cond,
3352 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3353 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003354 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003355
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 } else if (!strcmp(args[1], "auth")) {
3357 if (*(args[2]) == 0) {
3358 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3362 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_ALERT | ERR_ABORT;
3364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 }
3366 } else if (!strcmp(args[1], "scope")) {
3367 if (*(args[2]) == 0) {
3368 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3372 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003373 err_code |= ERR_ALERT | ERR_ABORT;
3374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 }
3376 } else if (!strcmp(args[1], "enable")) {
3377 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3378 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_ABORT;
3380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003382 } else if (!strcmp(args[1], "hide-version")) {
3383 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3384 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_ABORT;
3386 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003387 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003388 } else if (!strcmp(args[1], "show-legends")) {
3389 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3390 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3391 err_code |= ERR_ALERT | ERR_ABORT;
3392 goto out;
3393 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003394 } else if (!strcmp(args[1], "show-node")) {
3395
3396 if (*args[2]) {
3397 int i;
3398 char c;
3399
3400 for (i=0; args[2][i]; i++) {
3401 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003402 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3403 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003404 break;
3405 }
3406
3407 if (!i || args[2][i]) {
3408 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3409 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3410 file, linenum, args[0], args[1]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414 }
3415
3416 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3417 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3418 err_code |= ERR_ALERT | ERR_ABORT;
3419 goto out;
3420 }
3421 } else if (!strcmp(args[1], "show-desc")) {
3422 char *desc = NULL;
3423
3424 if (*args[2]) {
3425 int i, len=0;
3426 char *d;
3427
Willy Tarreau348acfe2014-04-14 15:00:39 +02003428 for (i = 2; *args[i]; i++)
3429 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003430
3431 desc = d = (char *)calloc(1, len);
3432
Willy Tarreau348acfe2014-04-14 15:00:39 +02003433 d += snprintf(d, desc + len - d, "%s", args[2]);
3434 for (i = 3; *args[i]; i++)
3435 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003436 }
3437
3438 if (!*args[2] && !global.desc)
3439 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3440 file, linenum, args[1]);
3441 else {
3442 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3443 free(desc);
3444 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3445 err_code |= ERR_ALERT | ERR_ABORT;
3446 goto out;
3447 }
3448 free(desc);
3449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003450 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003451stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003452 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 +01003453 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003456 }
3457 }
3458 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003459 int optnum;
3460
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003461 if (*(args[1]) == '\0') {
3462 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003467
3468 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3469 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003470 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3471 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3472 file, linenum, cfg_opts[optnum].name);
3473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
3475 }
Willy Tarreau93893792009-07-23 13:19:11 +02003476 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3477 err_code |= ERR_WARN;
3478 goto out;
3479 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003480
Willy Tarreau3842f002009-06-14 11:39:52 +02003481 curproxy->no_options &= ~cfg_opts[optnum].val;
3482 curproxy->options &= ~cfg_opts[optnum].val;
3483
3484 switch (kwm) {
3485 case KWM_STD:
3486 curproxy->options |= cfg_opts[optnum].val;
3487 break;
3488 case KWM_NO:
3489 curproxy->no_options |= cfg_opts[optnum].val;
3490 break;
3491 case KWM_DEF: /* already cleared */
3492 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003493 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003494
Willy Tarreau93893792009-07-23 13:19:11 +02003495 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003496 }
3497 }
3498
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003499 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3500 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003501 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3502 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3503 file, linenum, cfg_opts2[optnum].name);
3504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
3506 }
Willy Tarreau93893792009-07-23 13:19:11 +02003507 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3508 err_code |= ERR_WARN;
3509 goto out;
3510 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003511
Willy Tarreau3842f002009-06-14 11:39:52 +02003512 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3513 curproxy->options2 &= ~cfg_opts2[optnum].val;
3514
3515 switch (kwm) {
3516 case KWM_STD:
3517 curproxy->options2 |= cfg_opts2[optnum].val;
3518 break;
3519 case KWM_NO:
3520 curproxy->no_options2 |= cfg_opts2[optnum].val;
3521 break;
3522 case KWM_DEF: /* already cleared */
3523 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003524 }
Willy Tarreau93893792009-07-23 13:19:11 +02003525 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003526 }
3527 }
3528
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003529 /* HTTP options override each other. They can be cancelled using
3530 * "no option xxx" which only switches to default mode if the mode
3531 * was this one (useful for cancelling options set in defaults
3532 * sections).
3533 */
3534 if (strcmp(args[1], "httpclose") == 0) {
3535 if (kwm == KWM_STD) {
3536 curproxy->options &= ~PR_O_HTTP_MODE;
3537 curproxy->options |= PR_O_HTTP_PCL;
3538 goto out;
3539 }
3540 else if (kwm == KWM_NO) {
3541 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3542 curproxy->options &= ~PR_O_HTTP_MODE;
3543 goto out;
3544 }
3545 }
3546 else if (strcmp(args[1], "forceclose") == 0) {
3547 if (kwm == KWM_STD) {
3548 curproxy->options &= ~PR_O_HTTP_MODE;
3549 curproxy->options |= PR_O_HTTP_FCL;
3550 goto out;
3551 }
3552 else if (kwm == KWM_NO) {
3553 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3554 curproxy->options &= ~PR_O_HTTP_MODE;
3555 goto out;
3556 }
3557 }
3558 else if (strcmp(args[1], "http-server-close") == 0) {
3559 if (kwm == KWM_STD) {
3560 curproxy->options &= ~PR_O_HTTP_MODE;
3561 curproxy->options |= PR_O_HTTP_SCL;
3562 goto out;
3563 }
3564 else if (kwm == KWM_NO) {
3565 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3566 curproxy->options &= ~PR_O_HTTP_MODE;
3567 goto out;
3568 }
3569 }
3570 else if (strcmp(args[1], "http-keep-alive") == 0) {
3571 if (kwm == KWM_STD) {
3572 curproxy->options &= ~PR_O_HTTP_MODE;
3573 curproxy->options |= PR_O_HTTP_KAL;
3574 goto out;
3575 }
3576 else if (kwm == KWM_NO) {
3577 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3578 curproxy->options &= ~PR_O_HTTP_MODE;
3579 goto out;
3580 }
3581 }
3582 else if (strcmp(args[1], "http-tunnel") == 0) {
3583 if (kwm == KWM_STD) {
3584 curproxy->options &= ~PR_O_HTTP_MODE;
3585 curproxy->options |= PR_O_HTTP_TUN;
3586 goto out;
3587 }
3588 else if (kwm == KWM_NO) {
3589 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3590 curproxy->options &= ~PR_O_HTTP_MODE;
3591 goto out;
3592 }
3593 }
3594
Willy Tarreau3842f002009-06-14 11:39:52 +02003595 if (kwm != KWM_STD) {
3596 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003597 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003600 }
3601
Emeric Brun3a058f32009-06-30 18:26:00 +02003602 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003603 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003605 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003606 if (*(args[2]) != '\0') {
3607 if (!strcmp(args[2], "clf")) {
3608 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003609 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003610 } else {
3611 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003614 }
3615 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003616 if (curproxy->conf.logformat_string != default_http_log_format &&
3617 curproxy->conf.logformat_string != default_tcp_log_format &&
3618 curproxy->conf.logformat_string != clf_http_log_format)
3619 free(curproxy->conf.logformat_string);
3620 curproxy->conf.logformat_string = logformat;
3621
3622 free(curproxy->conf.lfs_file);
3623 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3624 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003625 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003626 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003628 if (curproxy->conf.logformat_string != default_http_log_format &&
3629 curproxy->conf.logformat_string != default_tcp_log_format &&
3630 curproxy->conf.logformat_string != clf_http_log_format)
3631 free(curproxy->conf.logformat_string);
3632 curproxy->conf.logformat_string = default_tcp_log_format;
3633
3634 free(curproxy->conf.lfs_file);
3635 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3636 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 else if (!strcmp(args[1], "tcpka")) {
3639 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003640 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003642
3643 if (curproxy->cap & PR_CAP_FE)
3644 curproxy->options |= PR_O_TCP_CLI_KA;
3645 if (curproxy->cap & PR_CAP_BE)
3646 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 }
3648 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003649 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_WARN;
3651
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003653 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003654 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003655 curproxy->options2 &= ~PR_O2_CHK_ANY;
3656 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 if (!*args[2]) { /* no argument */
3658 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3659 curproxy->check_len = strlen(DEF_CHECK_REQ);
3660 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003661 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 curproxy->check_req = (char *)malloc(reqlen);
3663 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003664 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003666 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 if (*args[4])
3668 reqlen += strlen(args[4]);
3669 else
3670 reqlen += strlen("HTTP/1.0");
3671
3672 curproxy->check_req = (char *)malloc(reqlen);
3673 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003674 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003676 }
3677 else if (!strcmp(args[1], "ssl-hello-chk")) {
3678 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003679 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003681
Willy Tarreaua534fea2008-08-03 12:19:50 +02003682 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003683 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003684 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003685 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 }
Willy Tarreau23677902007-05-08 23:50:35 +02003687 else if (!strcmp(args[1], "smtpchk")) {
3688 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003689 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003690 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003691 curproxy->options2 &= ~PR_O2_CHK_ANY;
3692 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003693
3694 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3695 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3696 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3697 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3698 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3699 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3700 curproxy->check_req = (char *)malloc(reqlen);
3701 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3702 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3703 } else {
3704 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3705 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3706 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3707 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3708 }
3709 }
3710 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003711 else if (!strcmp(args[1], "pgsql-check")) {
3712 /* use PostgreSQL request to check servers' health */
3713 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3714 err_code |= ERR_WARN;
3715
3716 free(curproxy->check_req);
3717 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003718 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003719 curproxy->options2 |= PR_O2_PGSQL_CHK;
3720
3721 if (*(args[2])) {
3722 int cur_arg = 2;
3723
3724 while (*(args[cur_arg])) {
3725 if (strcmp(args[cur_arg], "user") == 0) {
3726 char * packet;
3727 uint32_t packet_len;
3728 uint32_t pv;
3729
3730 /* suboption header - needs additional argument for it */
3731 if (*(args[cur_arg+1]) == 0) {
3732 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3733 file, linenum, args[0], args[1], args[cur_arg]);
3734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
3736 }
3737
3738 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3739 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3740 pv = htonl(0x30000); /* protocol version 3.0 */
3741
3742 packet = (char*) calloc(1, packet_len);
3743
3744 memcpy(packet + 4, &pv, 4);
3745
3746 /* copy "user" */
3747 memcpy(packet + 8, "user", 4);
3748
3749 /* copy username */
3750 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3751
3752 free(curproxy->check_req);
3753 curproxy->check_req = packet;
3754 curproxy->check_len = packet_len;
3755
3756 packet_len = htonl(packet_len);
3757 memcpy(packet, &packet_len, 4);
3758 cur_arg += 2;
3759 } else {
3760 /* unknown suboption - catchall */
3761 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3762 file, linenum, args[0], args[1]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
3766 } /* end while loop */
3767 }
3768 }
3769
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003770 else if (!strcmp(args[1], "redis-check")) {
3771 /* use REDIS PING request to check servers' health */
3772 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3773 err_code |= ERR_WARN;
3774
3775 free(curproxy->check_req);
3776 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003777 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003778 curproxy->options2 |= PR_O2_REDIS_CHK;
3779
3780 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3781 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3782 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3783 }
3784
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003785 else if (!strcmp(args[1], "mysql-check")) {
3786 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003787 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3788 err_code |= ERR_WARN;
3789
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003790 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003791 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003792 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003793 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003794
3795 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3796 * const char mysql40_client_auth_pkt[] = {
3797 * "\x0e\x00\x00" // packet length
3798 * "\x01" // packet number
3799 * "\x00\x00" // client capabilities
3800 * "\x00\x00\x01" // max packet
3801 * "haproxy\x00" // username (null terminated string)
3802 * "\x00" // filler (always 0x00)
3803 * "\x01\x00\x00" // packet length
3804 * "\x00" // packet number
3805 * "\x01" // COM_QUIT command
3806 * };
3807 */
3808
3809 if (*(args[2])) {
3810 int cur_arg = 2;
3811
3812 while (*(args[cur_arg])) {
3813 if (strcmp(args[cur_arg], "user") == 0) {
3814 char *mysqluser;
3815 int packetlen, reqlen, userlen;
3816
3817 /* suboption header - needs additional argument for it */
3818 if (*(args[cur_arg+1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3820 file, linenum, args[0], args[1], args[cur_arg]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 mysqluser = args[cur_arg + 1];
3825 userlen = strlen(mysqluser);
3826 packetlen = userlen + 7;
3827 reqlen = packetlen + 9;
3828
3829 free(curproxy->check_req);
3830 curproxy->check_req = (char *)calloc(1, reqlen);
3831 curproxy->check_len = reqlen;
3832
3833 snprintf(curproxy->check_req, 4, "%c%c%c",
3834 ((unsigned char) packetlen & 0xff),
3835 ((unsigned char) (packetlen >> 8) & 0xff),
3836 ((unsigned char) (packetlen >> 16) & 0xff));
3837
3838 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003839 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003840 curproxy->check_req[8] = 1;
3841 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3842 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3843 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3844 cur_arg += 2;
3845 } else {
3846 /* unknown suboption - catchall */
3847 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3848 file, linenum, args[0], args[1]);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852 } /* end while loop */
3853 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003854 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003855 else if (!strcmp(args[1], "ldap-check")) {
3856 /* use LDAP request to check servers' health */
3857 free(curproxy->check_req);
3858 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003859 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003860 curproxy->options2 |= PR_O2_LDAP_CHK;
3861
3862 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3863 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3864 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3865 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003866 else if (!strcmp(args[1], "tcp-check")) {
3867 /* use raw TCPCHK send/expect to check servers' health */
3868 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3869 err_code |= ERR_WARN;
3870
3871 free(curproxy->check_req);
3872 curproxy->check_req = NULL;
3873 curproxy->options2 &= ~PR_O2_CHK_ANY;
3874 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3875 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003876 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003877 int cur_arg;
3878
3879 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3880 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003881 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003882
Willy Tarreau87cf5142011-08-19 22:57:24 +02003883 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003884
3885 free(curproxy->fwdfor_hdr_name);
3886 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3887 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3888
3889 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3890 cur_arg = 2;
3891 while (*(args[cur_arg])) {
3892 if (!strcmp(args[cur_arg], "except")) {
3893 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003894 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003895 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3896 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003899 }
3900 /* flush useless bits */
3901 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003902 cur_arg += 2;
3903 } else if (!strcmp(args[cur_arg], "header")) {
3904 /* suboption header - needs additional argument for it */
3905 if (*(args[cur_arg+1]) == 0) {
3906 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3907 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003910 }
3911 free(curproxy->fwdfor_hdr_name);
3912 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3913 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3914 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003915 } else if (!strcmp(args[cur_arg], "if-none")) {
3916 curproxy->options &= ~PR_O_FF_ALWAYS;
3917 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003918 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003919 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003920 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003921 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003924 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003925 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003926 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003927 else if (!strcmp(args[1], "originalto")) {
3928 int cur_arg;
3929
3930 /* insert x-original-to field, but not for the IP address listed as an except.
3931 * set default options (ie: bitfield, header name, etc)
3932 */
3933
3934 curproxy->options |= PR_O_ORGTO;
3935
3936 free(curproxy->orgto_hdr_name);
3937 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3938 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3939
Willy Tarreau87cf5142011-08-19 22:57:24 +02003940 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003941 cur_arg = 2;
3942 while (*(args[cur_arg])) {
3943 if (!strcmp(args[cur_arg], "except")) {
3944 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003945 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 +02003946 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3947 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003950 }
3951 /* flush useless bits */
3952 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3953 cur_arg += 2;
3954 } else if (!strcmp(args[cur_arg], "header")) {
3955 /* suboption header - needs additional argument for it */
3956 if (*(args[cur_arg+1]) == 0) {
3957 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3958 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003961 }
3962 free(curproxy->orgto_hdr_name);
3963 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3964 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3965 cur_arg += 2;
3966 } else {
3967 /* unknown suboption - catchall */
3968 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3969 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003972 }
3973 } /* end while loop */
3974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 else {
3976 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 }
Willy Tarreau93893792009-07-23 13:19:11 +02003980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003982 else if (!strcmp(args[0], "default_backend")) {
3983 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003985
3986 if (*(args[1]) == 0) {
3987 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003990 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003991 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003992 curproxy->defbe.name = strdup(args[1]);
3993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003995 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003997
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003998 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3999 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 /* enable reconnections to dispatch */
4002 curproxy->options |= PR_O_REDISP;
4003 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004004 else if (!strcmp(args[0], "http-check")) {
4005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004006 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004007
4008 if (strcmp(args[1], "disable-on-404") == 0) {
4009 /* enable a graceful server shutdown on an HTTP 404 response */
4010 curproxy->options |= PR_O_DISABLE404;
4011 }
Willy Tarreauef781042010-01-27 11:53:01 +01004012 else if (strcmp(args[1], "send-state") == 0) {
4013 /* enable emission of the apparent state of a server in HTTP checks */
4014 curproxy->options2 |= PR_O2_CHK_SNDST;
4015 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004016 else if (strcmp(args[1], "expect") == 0) {
4017 const char *ptr_arg;
4018 int cur_arg;
4019
4020 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4021 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
4024 }
4025
4026 cur_arg = 2;
4027 /* consider exclamation marks, sole or at the beginning of a word */
4028 while (*(ptr_arg = args[cur_arg])) {
4029 while (*ptr_arg == '!') {
4030 curproxy->options2 ^= PR_O2_EXP_INV;
4031 ptr_arg++;
4032 }
4033 if (*ptr_arg)
4034 break;
4035 cur_arg++;
4036 }
4037 /* now ptr_arg points to the beginning of a word past any possible
4038 * exclamation mark, and cur_arg is the argument which holds this word.
4039 */
4040 if (strcmp(ptr_arg, "status") == 0) {
4041 if (!*(args[cur_arg + 1])) {
4042 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4043 file, linenum, args[0], args[1], ptr_arg);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004048 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004049 curproxy->expect_str = strdup(args[cur_arg + 1]);
4050 }
4051 else if (strcmp(ptr_arg, "string") == 0) {
4052 if (!*(args[cur_arg + 1])) {
4053 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4054 file, linenum, args[0], args[1], ptr_arg);
4055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
4057 }
4058 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004059 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004060 curproxy->expect_str = strdup(args[cur_arg + 1]);
4061 }
4062 else if (strcmp(ptr_arg, "rstatus") == 0) {
4063 if (!*(args[cur_arg + 1])) {
4064 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4065 file, linenum, args[0], args[1], ptr_arg);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004070 free(curproxy->expect_str);
4071 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4072 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004073 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4074 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4075 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4076 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080 }
4081 else if (strcmp(ptr_arg, "rstring") == 0) {
4082 if (!*(args[cur_arg + 1])) {
4083 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4084 file, linenum, args[0], args[1], ptr_arg);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
4088 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004089 free(curproxy->expect_str);
4090 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4091 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004092 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4093 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4094 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4095 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
4099 }
4100 else {
4101 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4102 file, linenum, args[0], args[1], ptr_arg);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004107 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004108 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 +02004109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004111 }
4112 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004113 else if (!strcmp(args[0], "tcp-check")) {
4114 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4115 err_code |= ERR_WARN;
4116
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004117 if (strcmp(args[1], "connect") == 0) {
4118 const char *ptr_arg;
4119 int cur_arg;
4120 struct tcpcheck_rule *tcpcheck;
4121 struct list *l;
4122
4123 /* check if first rule is also a 'connect' action */
4124 l = (struct list *)&curproxy->tcpcheck_rules;
4125 if (l->p != l->n) {
4126 tcpcheck = (struct tcpcheck_rule *)l->n;
4127 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4128 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4129 file, linenum);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133 }
4134
4135 cur_arg = 2;
4136 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4137 tcpcheck->action = TCPCHK_ACT_CONNECT;
4138
4139 /* parsing each parameters to fill up the rule */
4140 while (*(ptr_arg = args[cur_arg])) {
4141 /* tcp port */
4142 if (strcmp(args[cur_arg], "port") == 0) {
4143 if ( (atol(args[cur_arg + 1]) > 65535) ||
4144 (atol(args[cur_arg + 1]) < 1) ){
4145 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4146 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150 tcpcheck->port = atol(args[cur_arg + 1]);
4151 cur_arg += 2;
4152 }
4153 /* send proxy protocol */
4154 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4155 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4156 cur_arg++;
4157 }
4158#ifdef USE_OPENSSL
4159 else if (strcmp(args[cur_arg], "ssl") == 0) {
4160 curproxy->options |= PR_O_TCPCHK_SSL;
4161 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4162 cur_arg++;
4163 }
4164#endif /* USE_OPENSSL */
4165 else {
4166#ifdef USE_OPENSSL
4167 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4168#else /* USE_OPENSSL */
4169 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4170#endif /* USE_OPENSSL */
4171 file, linenum, args[0], args[1], args[cur_arg]);
4172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
4174 }
4175
4176 }
4177
4178 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4179 }
4180 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004181 if (! *(args[2]) ) {
4182 /* SEND string expected */
4183 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4184 file, linenum, args[0], args[1], args[2]);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 } else {
4188 struct tcpcheck_rule *tcpcheck;
4189
4190 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4191
4192 tcpcheck->action = TCPCHK_ACT_SEND;
4193 tcpcheck->string_len = strlen(args[2]);
4194 tcpcheck->string = strdup(args[2]);
4195 tcpcheck->expect_regex = NULL;
4196
4197 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4198 }
4199 }
4200 else if (strcmp(args[1], "send-binary") == 0) {
4201 if (! *(args[2]) ) {
4202 /* SEND binary string expected */
4203 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4204 file, linenum, args[0], args[1], args[2]);
4205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
4207 } else {
4208 struct tcpcheck_rule *tcpcheck;
4209 char *err = NULL;
4210
4211 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4212
4213 tcpcheck->action = TCPCHK_ACT_SEND;
4214 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4215 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4216 file, linenum, args[0], args[1], args[2], err);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
4220 tcpcheck->expect_regex = NULL;
4221
4222 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4223 }
4224 }
4225 else if (strcmp(args[1], "expect") == 0) {
4226 const char *ptr_arg;
4227 int cur_arg;
4228 int inverse = 0;
4229
4230 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4231 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235
4236 cur_arg = 2;
4237 /* consider exclamation marks, sole or at the beginning of a word */
4238 while (*(ptr_arg = args[cur_arg])) {
4239 while (*ptr_arg == '!') {
4240 inverse = !inverse;
4241 ptr_arg++;
4242 }
4243 if (*ptr_arg)
4244 break;
4245 cur_arg++;
4246 }
4247 /* now ptr_arg points to the beginning of a word past any possible
4248 * exclamation mark, and cur_arg is the argument which holds this word.
4249 */
4250 if (strcmp(ptr_arg, "binary") == 0) {
4251 if (!*(args[cur_arg + 1])) {
4252 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4253 file, linenum, args[0], args[1], ptr_arg);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257 struct tcpcheck_rule *tcpcheck;
4258 char *err = NULL;
4259
4260 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4261
4262 tcpcheck->action = TCPCHK_ACT_EXPECT;
4263 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4264 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4265 file, linenum, args[0], args[1], args[2], err);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269 tcpcheck->expect_regex = NULL;
4270 tcpcheck->inverse = inverse;
4271
4272 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4273 }
4274 else if (strcmp(ptr_arg, "string") == 0) {
4275 if (!*(args[cur_arg + 1])) {
4276 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4277 file, linenum, args[0], args[1], ptr_arg);
4278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
4280 }
4281 struct tcpcheck_rule *tcpcheck;
4282
4283 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4284
4285 tcpcheck->action = TCPCHK_ACT_EXPECT;
4286 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4287 tcpcheck->string = strdup(args[cur_arg + 1]);
4288 tcpcheck->expect_regex = NULL;
4289 tcpcheck->inverse = inverse;
4290
4291 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4292 }
4293 else if (strcmp(ptr_arg, "rstring") == 0) {
4294 if (!*(args[cur_arg + 1])) {
4295 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4296 file, linenum, args[0], args[1], ptr_arg);
4297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
4300 struct tcpcheck_rule *tcpcheck;
4301
4302 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4303
4304 tcpcheck->action = TCPCHK_ACT_EXPECT;
4305 tcpcheck->string_len = 0;
4306 tcpcheck->string = NULL;
4307 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4308 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4309 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4310 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
4313 }
4314 tcpcheck->inverse = inverse;
4315
4316 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4317 }
4318 else {
4319 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4320 file, linenum, args[0], args[1], ptr_arg);
4321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324 }
4325 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004326 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004331 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004332 if (curproxy == &defproxy) {
4333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004336 }
4337
Willy Tarreaub80c2302007-11-30 20:51:32 +01004338 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004339 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004340
4341 if (strcmp(args[1], "fail") == 0) {
4342 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004343 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004344 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4345 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004348 }
4349
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004350 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4351 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4352 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004355 }
4356 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4357 }
4358 else {
4359 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004362 }
4363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004364#ifdef TPROXY
4365 else if (!strcmp(args[0], "transparent")) {
4366 /* enable transparent proxy connections */
4367 curproxy->options |= PR_O_TRANSP;
4368 }
4369#endif
4370 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004371 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004372 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004373
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 if (*(args[1]) == 0) {
4375 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 }
4379 curproxy->maxconn = atol(args[1]);
4380 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004381 else if (!strcmp(args[0], "backlog")) { /* backlog */
4382 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004384
4385 if (*(args[1]) == 0) {
4386 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004389 }
4390 curproxy->backlog = atol(args[1]);
4391 }
Willy Tarreau86034312006-12-29 00:10:33 +01004392 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004395
Willy Tarreau86034312006-12-29 00:10:33 +01004396 if (*(args[1]) == 0) {
4397 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004400 }
4401 curproxy->fullconn = atol(args[1]);
4402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4404 if (*(args[1]) == 0) {
4405 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004408 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004409 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4410 if (err) {
4411 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4412 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004415 }
4416 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 }
4418 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004419 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004420 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004421 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004422
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 if (curproxy == &defproxy) {
4424 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004428 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004430
Willy Tarreau902636f2013-03-10 19:44:48 +01004431 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004432 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004433 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004434 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004435 goto out;
4436 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004437
4438 proto = protocol_by_family(sk->ss_family);
4439 if (!proto || !proto->connect) {
4440 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4441 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
4444 }
4445
4446 if (port1 != port2) {
4447 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4448 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004452
4453 if (!port1) {
4454 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4455 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
4458 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004459
Willy Tarreaud5191e72010-02-09 20:50:45 +01004460 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004461 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 }
4463 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004464 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004466
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004467 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4468 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004473 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004474 /**
4475 * The syntax for hash-type config element is
4476 * hash-type {map-based|consistent} [[<algo>] avalanche]
4477 *
4478 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4479 */
4480 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004481
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004482 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4483 err_code |= ERR_WARN;
4484
4485 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004486 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4487 }
4488 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004489 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4490 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004491 else if (strcmp(args[1], "avalanche") == 0) {
4492 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]);
4493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004495 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004496 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004497 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004498 err_code |= ERR_ALERT | ERR_FATAL;
4499 goto out;
4500 }
Bhaskar98634f02013-10-29 23:30:51 -04004501
4502 /* set the hash function to use */
4503 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004504 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004505 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004506
4507 /* if consistent with no argument, then avalanche modifier is also applied */
4508 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4509 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004510 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004511 /* set the hash function */
4512 if (!strcmp(args[2], "sdbm")) {
4513 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4514 }
4515 else if (!strcmp(args[2], "djb2")) {
4516 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004517 } else if (!strcmp(args[2], "wt6")) {
4518 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004519 }
4520 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004521 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 -05004522 err_code |= ERR_ALERT | ERR_FATAL;
4523 goto out;
4524 }
4525
4526 /* set the hash modifier */
4527 if (!strcmp(args[3], "avalanche")) {
4528 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4529 }
4530 else if (*args[3]) {
4531 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
4534 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004535 }
William Lallemanda73203e2012-03-12 12:48:57 +01004536 }
William Lallemanda73203e2012-03-12 12:48:57 +01004537 else if (strcmp(args[0], "unique-id-format") == 0) {
4538 if (!*(args[1])) {
4539 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
4542 }
William Lallemand3203ff42012-11-11 17:30:56 +01004543 if (*(args[2])) {
4544 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
4547 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004548 free(curproxy->conf.uniqueid_format_string);
4549 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004550
Willy Tarreau62a61232013-04-12 18:13:46 +02004551 free(curproxy->conf.uif_file);
4552 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4553 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004554 }
William Lallemanda73203e2012-03-12 12:48:57 +01004555
4556 else if (strcmp(args[0], "unique-id-header") == 0) {
4557 if (!*(args[1])) {
4558 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
4561 }
4562 free(curproxy->header_unique_id);
4563 curproxy->header_unique_id = strdup(args[1]);
4564 }
4565
William Lallemand723b73a2012-02-08 16:37:49 +01004566 else if (strcmp(args[0], "log-format") == 0) {
4567 if (!*(args[1])) {
4568 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
4571 }
William Lallemand3203ff42012-11-11 17:30:56 +01004572 if (*(args[2])) {
4573 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
4576 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004577
Willy Tarreau62a61232013-04-12 18:13:46 +02004578 if (curproxy->conf.logformat_string != default_http_log_format &&
4579 curproxy->conf.logformat_string != default_tcp_log_format &&
4580 curproxy->conf.logformat_string != clf_http_log_format)
4581 free(curproxy->conf.logformat_string);
4582 curproxy->conf.logformat_string = strdup(args[1]);
4583
4584 free(curproxy->conf.lfs_file);
4585 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4586 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004587
4588 /* get a chance to improve log-format error reporting by
4589 * reporting the correct line-number when possible.
4590 */
4591 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4592 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4593 file, linenum, curproxy->id);
4594 err_code |= ERR_WARN;
4595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
William Lallemand723b73a2012-02-08 16:37:49 +01004597
William Lallemand0f99e342011-10-12 17:50:54 +02004598 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4599 /* delete previous herited or defined syslog servers */
4600 struct logsrv *back;
4601
4602 if (*(args[1]) != 0) {
4603 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
4607
William Lallemand723b73a2012-02-08 16:37:49 +01004608 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4609 LIST_DEL(&tmplogsrv->list);
4610 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004611 }
4612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004614 struct logsrv *logsrv;
4615
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004617 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004618 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004619 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004620 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004621 LIST_INIT(&node->list);
4622 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624 }
4625 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004626 struct sockaddr_storage *sk;
4627 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004628
4629 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630
William Lallemand0f99e342011-10-12 17:50:54 +02004631 logsrv->facility = get_log_facility(args[2]);
4632 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
4636
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 }
4638
William Lallemand0f99e342011-10-12 17:50:54 +02004639 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004641 logsrv->level = get_log_level(args[3]);
4642 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
4646
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 }
4648 }
4649
William Lallemand0f99e342011-10-12 17:50:54 +02004650 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004651 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004652 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004653 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004654 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
4657
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004658 }
4659 }
4660
Willy Tarreau902636f2013-03-10 19:44:48 +01004661 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004662 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004663 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004664 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004665 goto out;
4666 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004667
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004668 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004669
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004670 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004671 if (port1 != port2) {
4672 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4673 file, linenum, args[0], args[1]);
4674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676 }
4677
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004678 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004679 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 }
William Lallemand0f99e342011-10-12 17:50:54 +02004681
4682 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
4684 else {
4685 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4686 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004687 err_code |= ERR_ALERT | ERR_FATAL;
4688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 }
4690 }
4691 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004692 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004693 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004694 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004695 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004696
Willy Tarreau977b8e42006-12-29 14:19:17 +01004697 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004698 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004699
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004701 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4702 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004703 err_code |= ERR_ALERT | ERR_FATAL;
4704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004706
4707 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004708 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4709 free(curproxy->conn_src.iface_name);
4710 curproxy->conn_src.iface_name = NULL;
4711 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004712
Willy Tarreau902636f2013-03-10 19:44:48 +01004713 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004714 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004715 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004716 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004717 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004718 goto out;
4719 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004720
4721 proto = protocol_by_family(sk->ss_family);
4722 if (!proto || !proto->connect) {
4723 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004724 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
4727 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004728
4729 if (port1 != port2) {
4730 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4731 file, linenum, args[0], args[1]);
4732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
4734 }
4735
Willy Tarreauef9a3602012-12-08 22:29:20 +01004736 curproxy->conn_src.source_addr = *sk;
4737 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004738
4739 cur_arg = 2;
4740 while (*(args[cur_arg])) {
4741 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004742#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4743#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004744 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004745 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4746 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004749 }
4750#endif
4751 if (!*args[cur_arg + 1]) {
4752 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4753 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004756 }
4757
4758 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004759 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4760 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004761 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004762 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4763 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004764 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4765 char *name, *end;
4766
4767 name = args[cur_arg+1] + 7;
4768 while (isspace(*name))
4769 name++;
4770
4771 end = name;
4772 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4773 end++;
4774
Willy Tarreauef9a3602012-12-08 22:29:20 +01004775 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4776 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4777 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4778 curproxy->conn_src.bind_hdr_len = end - name;
4779 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4780 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4781 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004782
4783 /* now look for an occurrence number */
4784 while (isspace(*end))
4785 end++;
4786 if (*end == ',') {
4787 end++;
4788 name = end;
4789 if (*end == '-')
4790 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004791 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004792 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004793 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004794 }
4795
Willy Tarreauef9a3602012-12-08 22:29:20 +01004796 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004797 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4798 " occurrences values smaller than %d.\n",
4799 file, linenum, MAX_HDR_HISTORY);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004803 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004804 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004805
Willy Tarreau902636f2013-03-10 19:44:48 +01004806 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004807 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004808 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004809 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004810 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004811 goto out;
4812 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004813
4814 proto = protocol_by_family(sk->ss_family);
4815 if (!proto || !proto->connect) {
4816 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4817 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004821
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004822 if (port1 != port2) {
4823 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4824 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004828 curproxy->conn_src.tproxy_addr = *sk;
4829 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004830 }
4831 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004832#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004833 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004834#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004835#else /* no TPROXY support */
4836 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004837 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004838 err_code |= ERR_ALERT | ERR_FATAL;
4839 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004840#endif
4841 cur_arg += 2;
4842 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004843 }
4844
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004845 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4846#ifdef SO_BINDTODEVICE
4847 if (!*args[cur_arg + 1]) {
4848 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4849 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004852 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004853 free(curproxy->conn_src.iface_name);
4854 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4855 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004856 global.last_checks |= LSTCHK_NETADM;
4857#else
4858 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4859 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004862#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004863 cur_arg += 2;
4864 continue;
4865 }
4866 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004867 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004872 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4873 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4874 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004879 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4881 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004885
4886 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004887 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004888 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004889 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 }
4892 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004893 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004894 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004895 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004896 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
4899 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004900 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004901 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004902 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004903 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 }
4906 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004908 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004909 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 }
4913 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004915 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004916 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004920 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004922 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004923 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004925 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004926 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004927 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004929 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004930 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004932 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004933 }
4934 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004936 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004937 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004938 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004939 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948
4949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004950 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004951 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
4955 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004957 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004958 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 }
4962 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004964 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004965 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004966 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 }
4969 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004971 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004972 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 }
4976 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004978 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004979 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004980 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004983 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004985 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004986 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004988 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004991 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004992
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 if (curproxy == &defproxy) {
4994 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004998 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 if (*(args[1]) == 0) {
5002 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005006
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005007 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005008 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5009 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5010 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
5013 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005014 err_code |= warnif_cond_conflicts(cond,
5015 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5016 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005017 }
5018 else if (*args[2]) {
5019 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5020 file, linenum, args[0], args[2]);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
5024
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005025 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005026 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005027 wl->s = strdup(args[1]);
5028 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005029 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
5031 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005038
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005040 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005041 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005042 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 }
5045 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005047 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005048 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005049 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 }
5052 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005054 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005055 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005058 }
5059 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005060 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 }
5066
Willy Tarreauade5ec42010-01-28 19:33:49 +01005067 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005068 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005069 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005070 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 }
5073 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005074 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005075 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005076 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005077 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 }
5080 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005081 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005082 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005083 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 }
5087 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005088 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005089
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 if (curproxy == &defproxy) {
5091 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005095 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 if (*(args[1]) == 0) {
5099 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
5103
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005104 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005105 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5106 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5107 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
5110 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005111 err_code |= warnif_cond_conflicts(cond,
5112 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5113 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005114 }
5115 else if (*args[2]) {
5116 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5117 file, linenum, args[0], args[2]);
5118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
5120 }
5121
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005122 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005123 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005124 wl->s = strdup(args[1]);
5125 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127 else if (!strcmp(args[0], "errorloc") ||
5128 !strcmp(args[0], "errorloc302") ||
5129 !strcmp(args[0], "errorloc303")) { /* error location */
5130 int errnum, errlen;
5131 char *err;
5132
Willy Tarreau977b8e42006-12-29 14:19:17 +01005133 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005135
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005137 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
5141
5142 errnum = atol(args[1]);
5143 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005144 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5145 err = malloc(errlen);
5146 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005148 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5149 err = malloc(errlen);
5150 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
5152
Willy Tarreau0f772532006-12-23 20:51:41 +01005153 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5154 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005155 chunk_destroy(&curproxy->errmsg[rc]);
5156 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005157 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005160
5161 if (rc >= HTTP_ERR_SIZE) {
5162 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5163 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 free(err);
5165 }
5166 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005167 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5168 int errnum, errlen, fd;
5169 char *err;
5170 struct stat stat;
5171
5172 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005174
5175 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005176 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005179 }
5180
5181 fd = open(args[2], O_RDONLY);
5182 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5183 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5184 file, linenum, args[2], args[1]);
5185 if (fd >= 0)
5186 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005189 }
5190
Willy Tarreau27a674e2009-08-17 07:23:33 +02005191 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005192 errlen = stat.st_size;
5193 } else {
5194 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005195 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005197 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005198 }
5199
5200 err = malloc(errlen); /* malloc() must succeed during parsing */
5201 errnum = read(fd, err, errlen);
5202 if (errnum != errlen) {
5203 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5204 file, linenum, args[2], args[1]);
5205 close(fd);
5206 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005209 }
5210 close(fd);
5211
5212 errnum = atol(args[1]);
5213 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5214 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005215 chunk_destroy(&curproxy->errmsg[rc]);
5216 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005217 break;
5218 }
5219 }
5220
5221 if (rc >= HTTP_ERR_SIZE) {
5222 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5223 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005224 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005225 free(err);
5226 }
5227 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005228 else if (!strcmp(args[0], "compression")) {
5229 struct comp *comp;
5230 if (curproxy->comp == NULL) {
5231 comp = calloc(1, sizeof(struct comp));
5232 curproxy->comp = comp;
5233 } else {
5234 comp = curproxy->comp;
5235 }
5236
5237 if (!strcmp(args[1], "algo")) {
5238 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005239 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005240
William Lallemand82fe75c2012-10-23 10:25:10 +02005241 cur_arg = 2;
5242 if (!*args[cur_arg]) {
5243 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5244 file, linenum, args[0]);
5245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
5248 while (*(args[cur_arg])) {
5249 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5250 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5251 file, linenum, args[0], args[cur_arg]);
5252 err_code |= ERR_ALERT | ERR_FATAL;
5253 goto out;
5254 }
William Lallemand552df672012-11-07 13:21:47 +01005255 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5256 curproxy->comp->algos->end(&ctx);
5257 } else {
5258 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5259 file, linenum, args[0], args[cur_arg]);
5260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005263 cur_arg ++;
5264 continue;
5265 }
5266 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005267 else if (!strcmp(args[1], "offload")) {
5268 comp->offload = 1;
5269 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005270 else if (!strcmp(args[1], "type")) {
5271 int cur_arg;
5272 cur_arg = 2;
5273 if (!*args[cur_arg]) {
5274 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5275 file, linenum, args[0]);
5276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
5278 }
5279 while (*(args[cur_arg])) {
5280 comp_append_type(comp, args[cur_arg]);
5281 cur_arg ++;
5282 continue;
5283 }
5284 }
5285 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005286 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005287 file, linenum, args[0]);
5288 err_code |= ERR_ALERT | ERR_FATAL;
5289 goto out;
5290 }
5291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005293 struct cfg_kw_list *kwl;
5294 int index;
5295
5296 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5297 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5298 if (kwl->kw[index].section != CFG_LISTEN)
5299 continue;
5300 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5301 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005302 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005303 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005304 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005307 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005308 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005309 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_WARN;
5311 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005312 }
Willy Tarreau93893792009-07-23 13:19:11 +02005313 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005314 }
5315 }
5316 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005317
Willy Tarreau6daf3432008-01-22 16:44:08 +01005318 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 }
Willy Tarreau93893792009-07-23 13:19:11 +02005322 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005323 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005324 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325}
5326
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005327int
5328cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5329{
5330
5331 int err_code = 0;
5332 const char *err;
5333
5334 if (!strcmp(args[0], "userlist")) { /* new userlist */
5335 struct userlist *newul;
5336
5337 if (!*args[1]) {
5338 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5339 file, linenum, args[0]);
5340 err_code |= ERR_ALERT | ERR_FATAL;
5341 goto out;
5342 }
5343
5344 err = invalid_char(args[1]);
5345 if (err) {
5346 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5347 file, linenum, *err, args[0], args[1]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351
5352 for (newul = userlist; newul; newul = newul->next)
5353 if (!strcmp(newul->name, args[1])) {
5354 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5355 file, linenum, args[1]);
5356 err_code |= ERR_WARN;
5357 goto out;
5358 }
5359
5360 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5361 if (!newul) {
5362 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5363 err_code |= ERR_ALERT | ERR_ABORT;
5364 goto out;
5365 }
5366
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005367 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005368 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005369 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5370 err_code |= ERR_ALERT | ERR_ABORT;
5371 goto out;
5372 }
5373
5374 newul->next = userlist;
5375 userlist = newul;
5376
5377 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005378 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005379 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005380 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005381
5382 if (!*args[1]) {
5383 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5384 file, linenum, args[0]);
5385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387 }
5388
5389 err = invalid_char(args[1]);
5390 if (err) {
5391 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5392 file, linenum, *err, args[0], args[1]);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
5396
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005397 for (ag = userlist->groups; ag; ag = ag->next)
5398 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005399 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5400 file, linenum, args[1], userlist->name);
5401 err_code |= ERR_ALERT;
5402 goto out;
5403 }
5404
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005405 ag = calloc(1, sizeof(*ag));
5406 if (!ag) {
5407 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5408 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005409 goto out;
5410 }
5411
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005412 ag->name = strdup(args[1]);
5413 if (!ag) {
5414 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5415 err_code |= ERR_ALERT | ERR_ABORT;
5416 goto out;
5417 }
5418
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005419 cur_arg = 2;
5420
5421 while (*args[cur_arg]) {
5422 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005423 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005424 cur_arg += 2;
5425 continue;
5426 } else {
5427 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5428 file, linenum, args[0]);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432 }
5433
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005434 ag->next = userlist->groups;
5435 userlist->groups = ag;
5436
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005437 } else if (!strcmp(args[0], "user")) { /* new user */
5438 struct auth_users *newuser;
5439 int cur_arg;
5440
5441 if (!*args[1]) {
5442 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5443 file, linenum, args[0]);
5444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
5447
5448 for (newuser = userlist->users; newuser; newuser = newuser->next)
5449 if (!strcmp(newuser->user, args[1])) {
5450 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5451 file, linenum, args[1], userlist->name);
5452 err_code |= ERR_ALERT;
5453 goto out;
5454 }
5455
5456 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5457 if (!newuser) {
5458 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5459 err_code |= ERR_ALERT | ERR_ABORT;
5460 goto out;
5461 }
5462
5463 newuser->user = strdup(args[1]);
5464
5465 newuser->next = userlist->users;
5466 userlist->users = newuser;
5467
5468 cur_arg = 2;
5469
5470 while (*args[cur_arg]) {
5471 if (!strcmp(args[cur_arg], "password")) {
5472#ifndef CONFIG_HAP_CRYPT
5473 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5474 file, linenum);
5475 err_code |= ERR_ALERT;
5476#endif
5477 newuser->pass = strdup(args[cur_arg + 1]);
5478 cur_arg += 2;
5479 continue;
5480 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5481 newuser->pass = strdup(args[cur_arg + 1]);
5482 newuser->flags |= AU_O_INSECURE;
5483 cur_arg += 2;
5484 continue;
5485 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005486 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005487 cur_arg += 2;
5488 continue;
5489 } else {
5490 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5491 file, linenum, args[0]);
5492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
5494 }
5495 }
5496 } else {
5497 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 }
5500
5501out:
5502 return err_code;
5503}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504
5505/*
5506 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005507 * Returns the error code, 0 if OK, or any combination of :
5508 * - ERR_ABORT: must abort ASAP
5509 * - ERR_FATAL: we can continue parsing but not start the service
5510 * - ERR_WARN: a warning has been emitted
5511 * - ERR_ALERT: an alert has been emitted
5512 * Only the two first ones can stop processing, the two others are just
5513 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005515int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005517 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 FILE *f;
5519 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005520 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005521 struct cfg_section *cs = NULL;
5522 struct cfg_section *ics;
5523
5524 /* Register internal sections */
5525 if (!cfg_register_section("listen", cfg_parse_listen) ||
5526 !cfg_register_section("frontend", cfg_parse_listen) ||
5527 !cfg_register_section("backend", cfg_parse_listen) ||
5528 !cfg_register_section("ruleset", cfg_parse_listen) ||
5529 !cfg_register_section("defaults", cfg_parse_listen) ||
5530 !cfg_register_section("global", cfg_parse_global) ||
5531 !cfg_register_section("userlist", cfg_parse_users) ||
5532 !cfg_register_section("peers", cfg_parse_peers))
5533 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005534
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 if ((f=fopen(file,"r")) == NULL)
5536 return -1;
5537
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005538 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005539 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005540 char *end;
5541 char *args[MAX_LINE_ARGS + 1];
5542 char *line = thisline;
5543
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 linenum++;
5545
5546 end = line + strlen(line);
5547
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005548 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5549 /* Check if we reached the limit and the last char is not \n.
5550 * Watch out for the last line without the terminating '\n'!
5551 */
5552 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005553 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005554 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005555 }
5556
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005558 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 line++;
5560
5561 arg = 0;
5562 args[arg] = line;
5563
5564 while (*line && arg < MAX_LINE_ARGS) {
5565 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5566 * C equivalent value. Other combinations left unchanged (eg: \1).
5567 */
5568 if (*line == '\\') {
5569 int skip = 0;
5570 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5571 *line = line[1];
5572 skip = 1;
5573 }
5574 else if (line[1] == 'r') {
5575 *line = '\r';
5576 skip = 1;
5577 }
5578 else if (line[1] == 'n') {
5579 *line = '\n';
5580 skip = 1;
5581 }
5582 else if (line[1] == 't') {
5583 *line = '\t';
5584 skip = 1;
5585 }
5586 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005587 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588 unsigned char hex1, hex2;
5589 hex1 = toupper(line[2]) - '0';
5590 hex2 = toupper(line[3]) - '0';
5591 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5592 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5593 *line = (hex1<<4) + hex2;
5594 skip = 3;
5595 }
5596 else {
5597 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005598 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 }
5600 }
5601 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005602 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 end -= skip;
5604 }
5605 line++;
5606 }
5607 else if (*line == '#' || *line == '\n' || *line == '\r') {
5608 /* end of string, end of loop */
5609 *line = 0;
5610 break;
5611 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005612 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005614 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005615 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 line++;
5617 args[++arg] = line;
5618 }
5619 else {
5620 line++;
5621 }
5622 }
5623
5624 /* empty line */
5625 if (!**args)
5626 continue;
5627
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005628 if (*line) {
5629 /* we had to stop due to too many args.
5630 * Let's terminate the string, print the offending part then cut the
5631 * last arg.
5632 */
5633 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5634 line++;
5635 *line = '\0';
5636
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005637 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005638 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005639 err_code |= ERR_ALERT | ERR_FATAL;
5640 args[arg] = line;
5641 }
5642
Willy Tarreau540abe42007-05-02 20:50:16 +02005643 /* zero out remaining args and ensure that at least one entry
5644 * is zeroed out.
5645 */
5646 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005647 args[arg] = line;
5648 }
5649
Willy Tarreau3842f002009-06-14 11:39:52 +02005650 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005651 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005652 char *tmp;
5653
Willy Tarreau3842f002009-06-14 11:39:52 +02005654 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005655 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005656 for (arg=0; *args[arg+1]; arg++)
5657 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005658 *tmp = '\0'; // fix the next arg to \0
5659 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005660 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005661 else if (!strcmp(args[0], "default")) {
5662 kwm = KWM_DEF;
5663 for (arg=0; *args[arg+1]; arg++)
5664 args[arg] = args[arg+1]; // shift args after inversion
5665 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005666
William Lallemand0f99e342011-10-12 17:50:54 +02005667 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5668 strcmp(args[0], "log") != 0) {
5669 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005670 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005671 }
5672
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005673 /* detect section start */
5674 list_for_each_entry(ics, &sections, list) {
5675 if (strcmp(args[0], ics->section_name) == 0) {
5676 cursection = ics->section_name;
5677 cs = ics;
5678 break;
5679 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005680 }
5681
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005683 if (cs)
5684 err_code |= cs->section_parser(file, linenum, args, kwm);
5685 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005686 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005689
5690 if (err_code & ERR_ABORT)
5691 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005693 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005695 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005696}
5697
Willy Tarreaubb925012009-07-23 13:36:36 +02005698/*
5699 * Returns the error code, 0 if OK, or any combination of :
5700 * - ERR_ABORT: must abort ASAP
5701 * - ERR_FATAL: we can continue parsing but not start the service
5702 * - ERR_WARN: a warning has been emitted
5703 * - ERR_ALERT: an alert has been emitted
5704 * Only the two first ones can stop processing, the two others are just
5705 * indicators.
5706 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005707int check_config_validity()
5708{
5709 int cfgerr = 0;
5710 struct proxy *curproxy = NULL;
5711 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005712 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005713 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005714 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005716 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 /*
5718 * Now, check for the integrity of all that we have collected.
5719 */
5720
5721 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005722 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723
Willy Tarreau193b8c62012-11-22 00:17:38 +01005724 if (!global.tune.max_http_hdr)
5725 global.tune.max_http_hdr = MAX_HTTP_HDR;
5726
5727 if (!global.tune.cookie_len)
5728 global.tune.cookie_len = CAPTURE_LEN;
5729
5730 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5731
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005732 /* Post initialisation of the users and groups lists. */
5733 err_code = userlist_postinit();
5734 if (err_code != ERR_NONE)
5735 goto out;
5736
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005737 /* first, we will invert the proxy list order */
5738 curproxy = NULL;
5739 while (proxy) {
5740 struct proxy *next;
5741
5742 next = proxy->next;
5743 proxy->next = curproxy;
5744 curproxy = proxy;
5745 if (!next)
5746 break;
5747 proxy = next;
5748 }
5749
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005751 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005752 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005753 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005754 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005755 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005756 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005757 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005758
Willy Tarreau050536d2012-10-04 08:47:34 +02005759 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005760 /* proxy ID not set, use automatic numbering with first
5761 * spare entry starting with next_pxid.
5762 */
5763 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5764 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5765 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005766 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005767 next_pxid++;
5768
Willy Tarreau55ea7572007-06-17 19:56:27 +02005769
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005771 /* ensure we don't keep listeners uselessly bound */
5772 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 curproxy = curproxy->next;
5774 continue;
5775 }
5776
Willy Tarreau16a21472012-11-19 12:39:59 +01005777 /* number of processes this proxy is bound to */
5778 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5779
Willy Tarreauff01a212009-03-15 13:46:16 +01005780 switch (curproxy->mode) {
5781 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005782 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005783 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005784 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5785 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005786 cfgerr++;
5787 }
5788
5789 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005790 Warning("config : servers will be ignored for %s '%s'.\n",
5791 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005792 break;
5793
5794 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005795 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005796 break;
5797
5798 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005799 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005800 break;
5801 }
5802
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005803 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005804 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005805 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005806 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5807 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005808 cfgerr++;
5809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005811 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005812 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5813 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005814 cfgerr++;
5815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005817 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005818 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5819 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005820 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005821 }
5822 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005823 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005824 /* If no LB algo is set in a backend, and we're not in
5825 * transparent mode, dispatch mode nor proxy mode, we
5826 * want to use balance roundrobin by default.
5827 */
5828 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5829 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005830 }
5831 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005832
Willy Tarreau1620ec32011-08-06 17:05:02 +02005833 if (curproxy->options & PR_O_DISPATCH)
5834 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5835 else if (curproxy->options & PR_O_HTTP_PROXY)
5836 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5837 else if (curproxy->options & PR_O_TRANSP)
5838 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005839
Willy Tarreau1620ec32011-08-06 17:05:02 +02005840 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5841 if (curproxy->options & PR_O_DISABLE404) {
5842 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5843 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5844 err_code |= ERR_WARN;
5845 curproxy->options &= ~PR_O_DISABLE404;
5846 }
5847 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5848 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5849 "send-state", proxy_type_str(curproxy), curproxy->id);
5850 err_code |= ERR_WARN;
5851 curproxy->options &= ~PR_O2_CHK_SNDST;
5852 }
Willy Tarreauef781042010-01-27 11:53:01 +01005853 }
5854
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005855 /* if a default backend was specified, let's find it */
5856 if (curproxy->defbe.name) {
5857 struct proxy *target;
5858
Alex Williams96532db2009-11-01 21:27:13 -05005859 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005860 if (!target) {
5861 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5862 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005863 cfgerr++;
5864 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005865 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5866 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005867 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005868 } else {
5869 free(curproxy->defbe.name);
5870 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005871 /* we force the backend to be present on at least all of
5872 * the frontend's processes.
5873 */
5874 target->bind_proc = curproxy->bind_proc ?
5875 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005876
5877 /* Emit a warning if this proxy also has some servers */
5878 if (curproxy->srv) {
5879 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5880 curproxy->id);
5881 err_code |= ERR_WARN;
5882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 }
5884 }
5885
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005886 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005887 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5888 /* map jump target for ACT_SETBE in req_rep chain */
5889 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005890 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005891 struct proxy *target;
5892
Willy Tarreaua496b602006-12-17 23:15:24 +01005893 if (exp->action != ACT_SETBE)
5894 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005895
Alex Williams96532db2009-11-01 21:27:13 -05005896 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005897 if (!target) {
5898 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5899 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005900 cfgerr++;
5901 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005902 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5903 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005904 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005905 } else {
5906 free((void *)exp->replace);
5907 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005908 /* we force the backend to be present on at least all of
5909 * the frontend's processes.
5910 */
5911 target->bind_proc = curproxy->bind_proc ?
5912 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005913 }
5914 }
5915 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005916
5917 /* find the target proxy for 'use_backend' rules */
5918 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005919 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005920 struct logformat_node *node;
5921 char *pxname;
5922
5923 /* Try to parse the string as a log format expression. If the result
5924 * of the parsing is only one entry containing a simple string, then
5925 * it's a standard string corresponding to a static rule, thus the
5926 * parsing is cancelled and be.name is restored to be resolved.
5927 */
5928 pxname = rule->be.name;
5929 LIST_INIT(&rule->be.expr);
5930 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
5931 curproxy->conf.args.file, curproxy->conf.args.line);
5932 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
5933
5934 if (!LIST_ISEMPTY(&rule->be.expr)) {
5935 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
5936 rule->dynamic = 1;
5937 free(pxname);
5938 continue;
5939 }
5940 /* simple string: free the expression and fall back to static rule */
5941 free(node->arg);
5942 free(node);
5943 }
5944
5945 rule->dynamic = 0;
5946 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005947
Alex Williams96532db2009-11-01 21:27:13 -05005948 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005949
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005950 if (!target) {
5951 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5952 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005953 cfgerr++;
5954 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005955 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5956 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005957 cfgerr++;
5958 } else {
5959 free((void *)rule->be.name);
5960 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005961 /* we force the backend to be present on at least all of
5962 * the frontend's processes.
5963 */
5964 target->bind_proc = curproxy->bind_proc ?
5965 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005966 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005967 }
5968
5969 /* find the target proxy for 'use_backend' rules */
5970 list_for_each_entry(srule, &curproxy->server_rules, list) {
5971 struct server *target = findserver(curproxy, srule->srv.name);
5972
5973 if (!target) {
5974 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5975 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5976 cfgerr++;
5977 continue;
5978 }
5979 free((void *)srule->srv.name);
5980 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005981 }
5982
Emeric Brunb982a3d2010-01-04 15:45:53 +01005983 /* find the target table for 'stick' rules */
5984 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5985 struct proxy *target;
5986
Emeric Brun1d33b292010-01-04 15:47:17 +01005987 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5988 if (mrule->flags & STK_IS_STORE)
5989 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5990
Emeric Brunb982a3d2010-01-04 15:45:53 +01005991 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005992 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005993 else
5994 target = curproxy;
5995
5996 if (!target) {
5997 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5998 curproxy->id, mrule->table.name);
5999 cfgerr++;
6000 }
6001 else if (target->table.size == 0) {
6002 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6003 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6004 cfgerr++;
6005 }
Willy Tarreau12785782012-04-27 21:37:17 +02006006 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6007 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006008 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6009 cfgerr++;
6010 }
6011 else {
6012 free((void *)mrule->table.name);
6013 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006014 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006015 }
6016 }
6017
6018 /* find the target table for 'store response' rules */
6019 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6020 struct proxy *target;
6021
Emeric Brun1d33b292010-01-04 15:47:17 +01006022 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6023
Emeric Brunb982a3d2010-01-04 15:45:53 +01006024 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006025 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006026 else
6027 target = curproxy;
6028
6029 if (!target) {
6030 Alert("Proxy '%s': unable to find store table '%s'.\n",
6031 curproxy->id, mrule->table.name);
6032 cfgerr++;
6033 }
6034 else if (target->table.size == 0) {
6035 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6036 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6037 cfgerr++;
6038 }
Willy Tarreau12785782012-04-27 21:37:17 +02006039 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6040 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006041 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6042 cfgerr++;
6043 }
6044 else {
6045 free((void *)mrule->table.name);
6046 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006047 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006048 }
6049 }
6050
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006051 /* find the target table for 'tcp-request' layer 4 rules */
6052 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6053 struct proxy *target;
6054
Willy Tarreaub4c84932013-07-23 19:15:30 +02006055 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006056 continue;
6057
6058 if (trule->act_prm.trk_ctr.table.n)
6059 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6060 else
6061 target = curproxy;
6062
6063 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006064 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6065 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006066 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006067 cfgerr++;
6068 }
6069 else if (target->table.size == 0) {
6070 Alert("Proxy '%s': table '%s' used but not configured.\n",
6071 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6072 cfgerr++;
6073 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006074 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6075 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6076 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 +01006077 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006078 cfgerr++;
6079 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006080 else {
6081 free(trule->act_prm.trk_ctr.table.n);
6082 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006083 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006084 * to pass a list of counters to track and allocate them right here using
6085 * stktable_alloc_data_type().
6086 */
6087 }
6088 }
6089
Willy Tarreaud1f96522010-08-03 19:34:32 +02006090 /* find the target table for 'tcp-request' layer 6 rules */
6091 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6092 struct proxy *target;
6093
Willy Tarreaub4c84932013-07-23 19:15:30 +02006094 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006095 continue;
6096
6097 if (trule->act_prm.trk_ctr.table.n)
6098 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6099 else
6100 target = curproxy;
6101
6102 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006103 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6104 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006105 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006106 cfgerr++;
6107 }
6108 else if (target->table.size == 0) {
6109 Alert("Proxy '%s': table '%s' used but not configured.\n",
6110 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6111 cfgerr++;
6112 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006113 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6114 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6115 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 +01006116 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006117 cfgerr++;
6118 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006119 else {
6120 free(trule->act_prm.trk_ctr.table.n);
6121 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006122 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006123 * to pass a list of counters to track and allocate them right here using
6124 * stktable_alloc_data_type().
6125 */
6126 }
6127 }
6128
Emeric Brun32da3c42010-09-23 18:39:19 +02006129 if (curproxy->table.peers.name) {
6130 struct peers *curpeers = peers;
6131
6132 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6133 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6134 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006135 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006136 break;
6137 }
6138 }
6139
6140 if (!curpeers) {
6141 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6142 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006143 free((void *)curproxy->table.peers.name);
6144 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006145 cfgerr++;
6146 }
6147 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006148 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6149 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006150 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006151 cfgerr++;
6152 }
6153 }
6154
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006155 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006156 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006157 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6158 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6159 "proxy", curproxy->id);
6160 cfgerr++;
6161 goto out_uri_auth_compat;
6162 }
6163
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006164 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006165 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006166 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006167 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006168
Willy Tarreau95fa4692010-02-01 13:05:50 +01006169 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6170 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006171
6172 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006173 uri_auth_compat_req[i++] = "realm";
6174 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6175 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006176
Willy Tarreau95fa4692010-02-01 13:05:50 +01006177 uri_auth_compat_req[i++] = "unless";
6178 uri_auth_compat_req[i++] = "{";
6179 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6180 uri_auth_compat_req[i++] = "}";
6181 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006182
Willy Tarreauff011f22011-01-06 17:51:27 +01006183 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6184 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006185 cfgerr++;
6186 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006187 }
6188
Willy Tarreauff011f22011-01-06 17:51:27 +01006189 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006190
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006191 if (curproxy->uri_auth->auth_realm) {
6192 free(curproxy->uri_auth->auth_realm);
6193 curproxy->uri_auth->auth_realm = NULL;
6194 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006195
6196 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006197 }
6198out_uri_auth_compat:
6199
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006200 /* compile the log format */
6201 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006202 if (curproxy->conf.logformat_string != default_http_log_format &&
6203 curproxy->conf.logformat_string != default_tcp_log_format &&
6204 curproxy->conf.logformat_string != clf_http_log_format)
6205 free(curproxy->conf.logformat_string);
6206 curproxy->conf.logformat_string = NULL;
6207 free(curproxy->conf.lfs_file);
6208 curproxy->conf.lfs_file = NULL;
6209 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006210 }
6211
Willy Tarreau62a61232013-04-12 18:13:46 +02006212 if (curproxy->conf.logformat_string) {
6213 curproxy->conf.args.ctx = ARGC_LOG;
6214 curproxy->conf.args.file = curproxy->conf.lfs_file;
6215 curproxy->conf.args.line = curproxy->conf.lfs_line;
6216 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006217 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006218 curproxy->conf.args.file = NULL;
6219 curproxy->conf.args.line = 0;
6220 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006221
Willy Tarreau62a61232013-04-12 18:13:46 +02006222 if (curproxy->conf.uniqueid_format_string) {
6223 curproxy->conf.args.ctx = ARGC_UIF;
6224 curproxy->conf.args.file = curproxy->conf.uif_file;
6225 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006226 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006227 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6228 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006229 curproxy->conf.args.file = NULL;
6230 curproxy->conf.args.line = 0;
6231 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006232
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006233 /* only now we can check if some args remain unresolved.
6234 * This must be done after the users and groups resolution.
6235 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006236 cfgerr += smp_resolve_args(curproxy);
6237 if (!cfgerr)
6238 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006239
Willy Tarreau2738a142006-07-08 17:28:09 +02006240 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006241 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006242 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006243 (!curproxy->timeout.connect ||
6244 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006245 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006246 " | While not properly invalid, you will certainly encounter various problems\n"
6247 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006248 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006249 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006250 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006251 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006252
Willy Tarreau1fa31262007-12-03 00:36:16 +01006253 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6254 * We must still support older configurations, so let's find out whether those
6255 * parameters have been set or must be copied from contimeouts.
6256 */
6257 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006258 if (!curproxy->timeout.tarpit ||
6259 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006260 /* tarpit timeout not set. We search in the following order:
6261 * default.tarpit, curr.connect, default.connect.
6262 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006263 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006264 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006265 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006266 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006267 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006268 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006269 }
6270 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006271 (!curproxy->timeout.queue ||
6272 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006273 /* queue timeout not set. We search in the following order:
6274 * default.queue, curr.connect, default.connect.
6275 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006276 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006277 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006278 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006279 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006280 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006281 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006282 }
6283 }
6284
Willy Tarreau1620ec32011-08-06 17:05:02 +02006285 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006286 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6287 curproxy->check_req = (char *)malloc(curproxy->check_len);
6288 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006289 }
6290
Willy Tarreau193b8c62012-11-22 00:17:38 +01006291 /* ensure that cookie capture length is not too large */
6292 if (curproxy->capture_len >= global.tune.cookie_len) {
6293 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6294 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6295 err_code |= ERR_WARN;
6296 curproxy->capture_len = global.tune.cookie_len - 1;
6297 }
6298
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006299 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006300 if (curproxy->nb_req_cap) {
6301 if (curproxy->mode == PR_MODE_HTTP) {
6302 curproxy->req_cap_pool = create_pool("ptrcap",
6303 curproxy->nb_req_cap * sizeof(char *),
6304 MEM_F_SHARED);
6305 } else {
6306 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6307 proxy_type_str(curproxy), curproxy->id);
6308 err_code |= ERR_WARN;
6309 curproxy->to_log &= ~LW_REQHDR;
6310 curproxy->nb_req_cap = 0;
6311 }
6312 }
6313
6314 if (curproxy->nb_rsp_cap) {
6315 if (curproxy->mode == PR_MODE_HTTP) {
6316 curproxy->rsp_cap_pool = create_pool("ptrcap",
6317 curproxy->nb_rsp_cap * sizeof(char *),
6318 MEM_F_SHARED);
6319 } else {
6320 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6321 proxy_type_str(curproxy), curproxy->id);
6322 err_code |= ERR_WARN;
6323 curproxy->to_log &= ~LW_REQHDR;
6324 curproxy->nb_rsp_cap = 0;
6325 }
6326 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006327
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 /* first, we will invert the servers list order */
6329 newsrv = NULL;
6330 while (curproxy->srv) {
6331 struct server *next;
6332
6333 next = curproxy->srv->next;
6334 curproxy->srv->next = newsrv;
6335 newsrv = curproxy->srv;
6336 if (!next)
6337 break;
6338 curproxy->srv = next;
6339 }
6340
Willy Tarreau17edc812014-01-03 12:14:34 +01006341 /* Check that no server name conflicts. This causes trouble in the stats.
6342 * We only emit a warning for the first conflict affecting each server,
6343 * in order to avoid combinatory explosion if all servers have the same
6344 * name. We do that only for servers which do not have an explicit ID,
6345 * because these IDs were made also for distinguishing them and we don't
6346 * want to annoy people who correctly manage them.
6347 */
6348 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6349 struct server *other_srv;
6350
6351 if (newsrv->puid)
6352 continue;
6353
6354 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6355 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6356 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6357 newsrv->conf.file, newsrv->conf.line,
6358 proxy_type_str(curproxy), curproxy->id,
6359 newsrv->id, other_srv->conf.line);
6360 break;
6361 }
6362 }
6363 }
6364
Willy Tarreaudd701652010-05-25 23:03:02 +02006365 /* assign automatic UIDs to servers which don't have one yet */
6366 next_id = 1;
6367 newsrv = curproxy->srv;
6368 while (newsrv != NULL) {
6369 if (!newsrv->puid) {
6370 /* server ID not set, use automatic numbering with first
6371 * spare entry starting with next_svid.
6372 */
6373 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6374 newsrv->conf.id.key = newsrv->puid = next_id;
6375 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6376 }
6377 next_id++;
6378 newsrv = newsrv->next;
6379 }
6380
Willy Tarreau20697042007-11-15 23:26:18 +01006381 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006382 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383
Willy Tarreau62c3be22012-01-20 13:12:32 +01006384 /*
6385 * If this server supports a maxconn parameter, it needs a dedicated
6386 * tasks to fill the emptied slots when a connection leaves.
6387 * Also, resolve deferred tracking dependency if needed.
6388 */
6389 newsrv = curproxy->srv;
6390 while (newsrv != NULL) {
6391 if (newsrv->minconn > newsrv->maxconn) {
6392 /* Only 'minconn' was specified, or it was higher than or equal
6393 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6394 * this will avoid further useless expensive computations.
6395 */
6396 newsrv->maxconn = newsrv->minconn;
6397 } else if (newsrv->maxconn && !newsrv->minconn) {
6398 /* minconn was not specified, so we set it to maxconn */
6399 newsrv->minconn = newsrv->maxconn;
6400 }
6401
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006402#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006403 if (newsrv->use_ssl || newsrv->check.use_ssl)
6404 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006405#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006406
Willy Tarreau2f075e92013-12-03 11:11:34 +01006407 /* set the check type on the server */
6408 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6409
Willy Tarreau62c3be22012-01-20 13:12:32 +01006410 if (newsrv->trackit) {
6411 struct proxy *px;
6412 struct server *srv;
6413 char *pname, *sname;
6414
6415 pname = newsrv->trackit;
6416 sname = strrchr(pname, '/');
6417
6418 if (sname)
6419 *sname++ = '\0';
6420 else {
6421 sname = pname;
6422 pname = NULL;
6423 }
6424
6425 if (pname) {
6426 px = findproxy(pname, PR_CAP_BE);
6427 if (!px) {
6428 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6429 proxy_type_str(curproxy), curproxy->id,
6430 newsrv->id, pname);
6431 cfgerr++;
6432 goto next_srv;
6433 }
6434 } else
6435 px = curproxy;
6436
6437 srv = findserver(px, sname);
6438 if (!srv) {
6439 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6440 proxy_type_str(curproxy), curproxy->id,
6441 newsrv->id, sname);
6442 cfgerr++;
6443 goto next_srv;
6444 }
6445
Willy Tarreauff5ae352013-12-11 20:36:34 +01006446 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006447 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6448 "tracking as it does not have checks enabled.\n",
6449 proxy_type_str(curproxy), curproxy->id,
6450 newsrv->id, px->id, srv->id);
6451 cfgerr++;
6452 goto next_srv;
6453 }
6454
6455 if (curproxy != px &&
6456 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6457 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6458 "tracking: disable-on-404 option inconsistency.\n",
6459 proxy_type_str(curproxy), curproxy->id,
6460 newsrv->id, px->id, srv->id);
6461 cfgerr++;
6462 goto next_srv;
6463 }
6464
6465 /* if the other server is forced disabled, we have to do the same here */
6466 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006467 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006468 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006469 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006470 }
6471
6472 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006473 newsrv->tracknext = srv->trackers;
6474 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006475
6476 free(newsrv->trackit);
6477 newsrv->trackit = NULL;
6478 }
6479 next_srv:
6480 newsrv = newsrv->next;
6481 }
6482
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006483 /* We have to initialize the server lookup mechanism depending
6484 * on what LB algorithm was choosen.
6485 */
6486
6487 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6488 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6489 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006490 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6491 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6492 init_server_map(curproxy);
6493 } else {
6494 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6495 fwrr_init_server_groups(curproxy);
6496 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006497 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006498
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006499 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006500 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6501 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6502 fwlc_init_server_tree(curproxy);
6503 } else {
6504 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6505 fas_init_server_tree(curproxy);
6506 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006507 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006508
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006509 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006510 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6511 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6512 chash_init_server_tree(curproxy);
6513 } else {
6514 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6515 init_server_map(curproxy);
6516 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006517 break;
6518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519
6520 if (curproxy->options & PR_O_LOGASAP)
6521 curproxy->to_log &= ~LW_BYTES;
6522
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006523 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006524 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006525 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6526 proxy_type_str(curproxy), curproxy->id);
6527 err_code |= ERR_WARN;
6528 }
6529
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006530 if (curproxy->mode != PR_MODE_HTTP) {
6531 int optnum;
6532
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006533 if (curproxy->uri_auth) {
6534 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6535 proxy_type_str(curproxy), curproxy->id);
6536 err_code |= ERR_WARN;
6537 curproxy->uri_auth = NULL;
6538 }
6539
Willy Tarreau87cf5142011-08-19 22:57:24 +02006540 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006541 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6542 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6543 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006544 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006545 }
6546
6547 if (curproxy->options & PR_O_ORGTO) {
6548 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6549 "originalto", proxy_type_str(curproxy), curproxy->id);
6550 err_code |= ERR_WARN;
6551 curproxy->options &= ~PR_O_ORGTO;
6552 }
6553
6554 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6555 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6556 (curproxy->cap & cfg_opts[optnum].cap) &&
6557 (curproxy->options & cfg_opts[optnum].val)) {
6558 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6559 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6560 err_code |= ERR_WARN;
6561 curproxy->options &= ~cfg_opts[optnum].val;
6562 }
6563 }
6564
6565 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6566 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6567 (curproxy->cap & cfg_opts2[optnum].cap) &&
6568 (curproxy->options2 & cfg_opts2[optnum].val)) {
6569 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6570 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6571 err_code |= ERR_WARN;
6572 curproxy->options2 &= ~cfg_opts2[optnum].val;
6573 }
6574 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006575
Pieter Baauwd551fb52013-05-08 22:49:23 +02006576#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006577 if (curproxy->conn_src.bind_hdr_occ) {
6578 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006579 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006580 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006581 err_code |= ERR_WARN;
6582 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006583#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006584 }
6585
Willy Tarreaubaaee002006-06-26 02:48:02 +02006586 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006587 * ensure that we're not cross-dressing a TCP server into HTTP.
6588 */
6589 newsrv = curproxy->srv;
6590 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006591 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006592 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6593 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006594 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006595 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006596
Willy Tarreau0cec3312011-10-31 13:49:26 +01006597 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6598 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6599 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6600 err_code |= ERR_WARN;
6601 }
6602
Willy Tarreau82ffa392013-08-13 17:19:08 +02006603 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6604 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6605 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6606 err_code |= ERR_WARN;
6607 }
6608
Pieter Baauwd551fb52013-05-08 22:49:23 +02006609#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006610 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6611 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006612 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 +01006613 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006614 err_code |= ERR_WARN;
6615 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006616#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006617 newsrv = newsrv->next;
6618 }
6619
Willy Tarreauc1a21672009-08-16 22:37:44 +02006620 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006621 if (!curproxy->accept)
6622 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006623
Willy Tarreauc1a21672009-08-16 22:37:44 +02006624 if (curproxy->tcp_req.inspect_delay ||
6625 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006626 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006627
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006628 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006629 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006630 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006631 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006632
6633 /* both TCP and HTTP must check switching rules */
6634 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6635 }
6636
6637 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006638 if (curproxy->tcp_req.inspect_delay ||
6639 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6640 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6641
Emeric Brun97679e72010-09-23 17:56:44 +02006642 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6643 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6644
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006645 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006646 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006647 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006648 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006649
6650 /* If the backend does requires RDP cookie persistence, we have to
6651 * enable the corresponding analyser.
6652 */
6653 if (curproxy->options2 & PR_O2_RDPC_PRST)
6654 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6655 }
6656
Emeric Brunc52962f2012-11-15 18:28:02 +01006657#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006658 /* Configure SSL for each bind line.
6659 * Note: if configuration fails at some point, the ->ctx member
6660 * remains NULL so that listeners can later detach.
6661 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006662 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006663 if (!bind_conf->is_ssl) {
6664 if (bind_conf->default_ctx) {
6665 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6666 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6667 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006668 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006669 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006670 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006671 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006672 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006673 cfgerr++;
6674 continue;
6675 }
6676
Emeric Brun4b3091e2012-09-24 15:48:52 +02006677 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006678 Alert("Unable to allocate SSL session cache.\n");
6679 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006680 continue;
6681 }
6682
Emeric Brunfc0421f2012-09-07 17:30:07 +02006683 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006684 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006685 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006686#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006687
Willy Tarreaue6b98942007-10-29 01:09:36 +01006688 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006689 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006690 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006691 if (!listener->luid) {
6692 /* listener ID not set, use automatic numbering with first
6693 * spare entry starting with next_luid.
6694 */
6695 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6696 listener->conf.id.key = listener->luid = next_id;
6697 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006698 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006699 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006700
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006701 /* enable separate counters */
6702 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6703 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006704 if (!listener->name)
6705 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006706 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006707
Willy Tarreaue6b98942007-10-29 01:09:36 +01006708 if (curproxy->options & PR_O_TCP_NOLING)
6709 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006710 if (!listener->maxconn)
6711 listener->maxconn = curproxy->maxconn;
6712 if (!listener->backlog)
6713 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006714 if (!listener->maxaccept)
6715 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6716
6717 /* we want to have an optimal behaviour on single process mode to
6718 * maximize the work at once, but in multi-process we want to keep
6719 * some fairness between processes, so we target half of the max
6720 * number of events to be balanced over all the processes the proxy
6721 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6722 * used to disable the limit.
6723 */
6724 if (listener->maxaccept > 0) {
6725 if (nbproc > 1)
6726 listener->maxaccept = (listener->maxaccept + 1) / 2;
6727 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6728 }
6729
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006730 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006731 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006732 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006733 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006734
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006735 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6736 listener->options |= LI_O_TCP_RULES;
6737
Willy Tarreaude3041d2010-05-31 10:56:17 +02006738 if (curproxy->mon_mask.s_addr)
6739 listener->options |= LI_O_CHK_MONNET;
6740
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006741 /* smart accept mode is automatic in HTTP mode */
6742 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006743 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006744 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6745 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006746 }
6747
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006748 /* Release unused SSL configs */
6749 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6750 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006751 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006752#ifdef USE_OPENSSL
6753 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006754 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006755 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006756 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006757 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006758#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006759 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006760
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006761 /* Check multi-process mode compatibility for the current proxy */
6762 if (global.nbproc > 1) {
6763 int nbproc = 0;
6764 if (curproxy->bind_proc) {
6765 int proc;
6766 for (proc = 0; proc < global.nbproc; proc++) {
6767 if (curproxy->bind_proc & (1 << proc)) {
6768 nbproc++;
6769 }
6770 }
6771 } else {
6772 nbproc = global.nbproc;
6773 }
6774 if (curproxy->table.peers.name) {
6775 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6776 curproxy->id);
6777 cfgerr++;
6778 }
6779 if (nbproc > 1) {
6780 if (curproxy->uri_auth) {
6781 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6782 curproxy->id);
6783 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6784 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6785 curproxy->id);
6786 }
6787 }
6788 if (curproxy->appsession_name) {
6789 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6790 curproxy->id);
6791 }
6792 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6793 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6794 curproxy->id);
6795 }
6796 }
6797 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006798
6799 /* create the task associated with the proxy */
6800 curproxy->task = task_new();
6801 if (curproxy->task) {
6802 curproxy->task->context = curproxy;
6803 curproxy->task->process = manage_proxy;
6804 /* no need to queue, it will be done automatically if some
6805 * listener gets limited.
6806 */
6807 curproxy->task->expire = TICK_ETERNITY;
6808 } else {
6809 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6810 curproxy->id);
6811 cfgerr++;
6812 }
6813
Willy Tarreaubaaee002006-06-26 02:48:02 +02006814 curproxy = curproxy->next;
6815 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006816
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006817 /* Check multi-process mode compatibility */
6818 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006819 if (global.stats_fe && !global.stats_fe->bind_proc) {
6820 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 +01006821 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006822 }
6823
6824 /* automatically compute fullconn if not set. We must not do it in the
6825 * loop above because cross-references are not yet fully resolved.
6826 */
6827 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6828 /* If <fullconn> is not set, let's set it to 10% of the sum of
6829 * the possible incoming frontend's maxconns.
6830 */
6831 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6832 struct proxy *fe;
6833 int total = 0;
6834
6835 /* sum up the number of maxconns of frontends which
6836 * reference this backend at least once or which are
6837 * the same one ('listen').
6838 */
6839 for (fe = proxy; fe; fe = fe->next) {
6840 struct switching_rule *rule;
6841 struct hdr_exp *exp;
6842 int found = 0;
6843
6844 if (!(fe->cap & PR_CAP_FE))
6845 continue;
6846
6847 if (fe == curproxy) /* we're on a "listen" instance */
6848 found = 1;
6849
6850 if (fe->defbe.be == curproxy) /* "default_backend" */
6851 found = 1;
6852
6853 /* check if a "use_backend" rule matches */
6854 if (!found) {
6855 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006856 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006857 found = 1;
6858 break;
6859 }
6860 }
6861 }
6862
6863 /* check if a "reqsetbe" rule matches */
6864 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6865 if (exp->action == ACT_SETBE &&
6866 (struct proxy *)exp->replace == curproxy) {
6867 found = 1;
6868 break;
6869 }
6870 }
6871
6872 /* now we've checked all possible ways to reference a backend
6873 * from a frontend.
6874 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006875 if (!found)
6876 continue;
6877 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006878 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006879 /* we have the sum of the maxconns in <total>. We only
6880 * keep 10% of that sum to set the default fullconn, with
6881 * a hard minimum of 1 (to avoid a divide by zero).
6882 */
6883 curproxy->fullconn = (total + 9) / 10;
6884 if (!curproxy->fullconn)
6885 curproxy->fullconn = 1;
6886 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006887 }
6888
Willy Tarreau056f5682010-06-06 15:51:11 +02006889 /* initialize stick-tables on backend capable proxies. This must not
6890 * be done earlier because the data size may be discovered while parsing
6891 * other proxies.
6892 */
Godbach9703e662013-12-11 21:11:41 +08006893 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006894 if (curproxy->state == PR_STSTOPPED)
6895 continue;
6896
Godbach9703e662013-12-11 21:11:41 +08006897 if (!stktable_init(&curproxy->table)) {
6898 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6899 cfgerr++;
6900 }
6901 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006902
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006903 /*
6904 * Recount currently required checks.
6905 */
6906
6907 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6908 int optnum;
6909
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006910 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6911 if (curproxy->options & cfg_opts[optnum].val)
6912 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006913
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006914 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6915 if (curproxy->options2 & cfg_opts2[optnum].val)
6916 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006917 }
6918
Willy Tarreau122541c2011-09-07 21:24:49 +02006919 if (peers) {
6920 struct peers *curpeers = peers, **last;
6921 struct peer *p, *pb;
6922
6923 /* Remove all peers sections which don't have a valid listener.
6924 * This can happen when a peers section is never referenced and
6925 * does not contain a local peer.
6926 */
6927 last = &peers;
6928 while (*last) {
6929 curpeers = *last;
6930 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01006931 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02006932 last = &curpeers->next;
6933 continue;
6934 }
6935
6936 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6937 curpeers->id, localpeer);
6938
6939 p = curpeers->remote;
6940 while (p) {
6941 pb = p->next;
6942 free(p->id);
6943 free(p);
6944 p = pb;
6945 }
6946
6947 /* Destroy and unlink this curpeers section.
6948 * Note: curpeers is backed up into *last.
6949 */
6950 free(curpeers->id);
6951 curpeers = curpeers->next;
6952 free(*last);
6953 *last = curpeers;
6954 }
6955 }
6956
Willy Tarreau34eb6712011-10-24 18:15:04 +02006957 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006958 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006959 MEM_F_SHARED);
6960
Willy Tarreaubb925012009-07-23 13:36:36 +02006961 if (cfgerr > 0)
6962 err_code |= ERR_ALERT | ERR_FATAL;
6963 out:
6964 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006965}
6966
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006967/*
6968 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6969 * parsing sessions.
6970 */
6971void cfg_register_keywords(struct cfg_kw_list *kwl)
6972{
6973 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6974}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006975
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006976/*
6977 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6978 */
6979void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6980{
6981 LIST_DEL(&kwl->list);
6982 LIST_INIT(&kwl->list);
6983}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006984
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006985/* this function register new section in the haproxy configuration file.
6986 * <section_name> is the name of this new section and <section_parser>
6987 * is the called parser. If two section declaration have the same name,
6988 * only the first declared is used.
6989 */
6990int cfg_register_section(char *section_name,
6991 int (*section_parser)(const char *, int, char **, int))
6992{
6993 struct cfg_section *cs;
6994
6995 cs = calloc(1, sizeof(*cs));
6996 if (!cs) {
6997 Alert("register section '%s': out of memory.\n", section_name);
6998 return 0;
6999 }
7000
7001 cs->section_name = section_name;
7002 cs->section_parser = section_parser;
7003
7004 LIST_ADDQ(&sections, &cs->list);
7005
7006 return 1;
7007}
7008
Willy Tarreaubaaee002006-06-26 02:48:02 +02007009/*
7010 * Local variables:
7011 * c-indent-level: 8
7012 * c-basic-offset: 8
7013 * End:
7014 */