blob: 344bde1058c3b9ae470deebb89dc627ce8857c56 [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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "quiet")) {
510 global.mode |= MODE_QUIET;
511 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200512 else if (!strcmp(args[0], "tune.maxpollevents")) {
513 if (global.tune.maxpollevents != 0) {
514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT;
516 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200517 }
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200522 }
523 global.tune.maxpollevents = atol(args[1]);
524 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100525 else if (!strcmp(args[0], "tune.maxaccept")) {
526 if (global.tune.maxaccept != 0) {
527 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200528 err_code |= ERR_ALERT;
529 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100530 }
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100535 }
536 global.tune.maxaccept = atol(args[1]);
537 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200538 else if (!strcmp(args[0], "tune.chksize")) {
539 if (*(args[1]) == 0) {
540 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT | ERR_FATAL;
542 goto out;
543 }
544 global.tune.chksize = atol(args[1]);
545 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200546#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100547 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200548 if (*(args[1]) == 0) {
549 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
550 err_code |= ERR_ALERT | ERR_FATAL;
551 goto out;
552 }
553 global.tune.sslcachesize = atol(args[1]);
554 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100555 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
556 unsigned int ssllifetime;
557 const char *res;
558
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564
565 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
566 if (res) {
567 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
568 file, linenum, *res, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572
573 global.tune.ssllifetime = ssllifetime;
574 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100575 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.tune.ssl_max_record = atol(args[1]);
582 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200583#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200584 else if (!strcmp(args[0], "tune.bufsize")) {
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.bufsize = atol(args[1]);
591 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
592 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100593 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100594 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200595 }
596 else if (!strcmp(args[0], "tune.maxrewrite")) {
597 if (*(args[1]) == 0) {
598 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT | ERR_FATAL;
600 goto out;
601 }
602 global.tune.maxrewrite = atol(args[1]);
603 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
604 global.tune.maxrewrite = global.tune.bufsize / 2;
605 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100606 else if (!strcmp(args[0], "tune.idletimer")) {
607 unsigned int idle;
608 const char *res;
609
610 if (*(args[1]) == 0) {
611 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
612 err_code |= ERR_ALERT | ERR_FATAL;
613 goto out;
614 }
615
616 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
617 if (res) {
618 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
619 file, linenum, *res, args[0]);
620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
622 }
623
624 if (idle > 65535) {
625 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628 }
629 global.tune.idle_timer = idle;
630 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100631 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
632 if (global.tune.client_rcvbuf != 0) {
633 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
634 err_code |= ERR_ALERT;
635 goto out;
636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.client_rcvbuf = atol(args[1]);
643 }
644 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
645 if (global.tune.server_rcvbuf != 0) {
646 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
647 err_code |= ERR_ALERT;
648 goto out;
649 }
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.server_rcvbuf = atol(args[1]);
656 }
657 else if (!strcmp(args[0], "tune.sndbuf.client")) {
658 if (global.tune.client_sndbuf != 0) {
659 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
660 err_code |= ERR_ALERT;
661 goto out;
662 }
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668 global.tune.client_sndbuf = atol(args[1]);
669 }
670 else if (!strcmp(args[0], "tune.sndbuf.server")) {
671 if (global.tune.server_sndbuf != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
673 err_code |= ERR_ALERT;
674 goto out;
675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.server_sndbuf = atol(args[1]);
682 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200683 else if (!strcmp(args[0], "tune.pipesize")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.pipesize = atol(args[1]);
690 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100691 else if (!strcmp(args[0], "tune.http.cookielen")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.cookie_len = atol(args[1]) + 1;
698 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200699 else if (!strcmp(args[0], "tune.http.maxhdr")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.max_http_hdr = atol(args[1]);
706 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100707 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
708#ifdef USE_ZLIB
709 if (*args[1]) {
710 global.tune.zlibmemlevel = atoi(args[1]);
711 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
712 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
713 file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 } else {
718 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
719 file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723#else
724 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
725 err_code |= ERR_ALERT | ERR_FATAL;
726 goto out;
727#endif
728 }
729 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
730#ifdef USE_ZLIB
731 if (*args[1]) {
732 global.tune.zlibwindowsize = atoi(args[1]);
733 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
734 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
735 file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739 } else {
740 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
741 file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745#else
746 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
749#endif
750 }
William Lallemandf3747832012-11-09 12:33:10 +0100751 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
752 if (*args[1]) {
753 global.tune.comp_maxlevel = atoi(args[1]);
754 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
755 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760 } else {
761 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
762 file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 else if (!strcmp(args[0], "uid")) {
768 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200769 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_ALERT;
771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 }
773 if (*(args[1]) == 0) {
774 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 global.uid = atol(args[1]);
779 }
780 else if (!strcmp(args[0], "gid")) {
781 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200782 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT;
784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 }
786 if (*(args[1]) == 0) {
787 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200788 err_code |= ERR_ALERT | ERR_FATAL;
789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200790 }
791 global.gid = atol(args[1]);
792 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200793 /* user/group name handling */
794 else if (!strcmp(args[0], "user")) {
795 struct passwd *ha_user;
796 if (global.uid != 0) {
797 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200798 err_code |= ERR_ALERT;
799 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200800 }
801 errno = 0;
802 ha_user = getpwnam(args[1]);
803 if (ha_user != NULL) {
804 global.uid = (int)ha_user->pw_uid;
805 }
806 else {
807 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 +0200808 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 }
811 else if (!strcmp(args[0], "group")) {
812 struct group *ha_group;
813 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200814 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT;
816 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200817 }
818 errno = 0;
819 ha_group = getgrnam(args[1]);
820 if (ha_group != NULL) {
821 global.gid = (int)ha_group->gr_gid;
822 }
823 else {
824 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 +0200825 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200826 }
827 }
828 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200830 if (*(args[1]) == 0) {
831 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 global.nbproc = atol(args[1]);
836 }
837 else if (!strcmp(args[0], "maxconn")) {
838 if (global.maxconn != 0) {
839 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200840 err_code |= ERR_ALERT;
841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200842 }
843 if (*(args[1]) == 0) {
844 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200847 }
848 global.maxconn = atol(args[1]);
849#ifdef SYSTEM_MAXCONN
850 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
851 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);
852 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200853 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 }
855#endif /* SYSTEM_MAXCONN */
856 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200857 else if (!strcmp(args[0], "maxsslconn")) {
858#ifdef USE_OPENSSL
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.maxsslconn = atol(args[1]);
865#else
Emeric Brun0914df82012-10-02 18:45:42 +0200866 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200869#endif
870 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100871 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
872#ifdef USE_OPENSSL
873 if (*(args[1]) == 0) {
874 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
875 err_code |= ERR_ALERT | ERR_FATAL;
876 goto out;
877 }
878 free(global.listen_default_ciphers);
879 global.listen_default_ciphers = strdup(args[1]);
880#else
881 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884#endif
885 }
886 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
887#ifdef USE_OPENSSL
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 free(global.connect_default_ciphers);
894 global.connect_default_ciphers = strdup(args[1]);
895#else
896 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899#endif
900 }
Emeric Brun850efd52014-01-29 12:24:34 +0100901 else if (!strcmp(args[0], "ssl-server-verify")) {
902 if (*(args[1]) == 0) {
903 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 if (strcmp(args[1],"none") == 0)
908 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
909 else if (strcmp(args[1],"required") == 0)
910 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
911 else {
912 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
916 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200917 else if (!strcmp(args[0], "maxconnrate")) {
918 if (global.cps_lim != 0) {
919 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
920 err_code |= ERR_ALERT;
921 goto out;
922 }
923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 global.cps_lim = atol(args[1]);
929 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200930 else if (!strcmp(args[0], "maxsessrate")) {
931 if (global.sps_lim != 0) {
932 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT;
934 goto out;
935 }
936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto out;
940 }
941 global.sps_lim = atol(args[1]);
942 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200943 else if (!strcmp(args[0], "maxsslrate")) {
944 if (global.ssl_lim != 0) {
945 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT;
947 goto out;
948 }
949 if (*(args[1]) == 0) {
950 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 global.ssl_lim = atol(args[1]);
955 }
William Lallemandd85f9172012-11-09 17:05:39 +0100956 else if (!strcmp(args[0], "maxcomprate")) {
957 if (*(args[1]) == 0) {
958 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto out;
961 }
962 global.comp_rate_lim = atoi(args[1]) * 1024;
963 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100964 else if (!strcmp(args[0], "maxpipes")) {
965 if (global.maxpipes != 0) {
966 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200967 err_code |= ERR_ALERT;
968 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100969 }
970 if (*(args[1]) == 0) {
971 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100974 }
975 global.maxpipes = atol(args[1]);
976 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100977 else if (!strcmp(args[0], "maxzlibmem")) {
978 if (*(args[1]) == 0) {
979 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
William Lallemande3a7d992012-11-20 11:25:20 +0100983 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100984 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100985 else if (!strcmp(args[0], "maxcompcpuusage")) {
986 if (*(args[1]) == 0) {
987 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
990 }
991 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100992 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100993 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
994 err_code |= ERR_ALERT | ERR_FATAL;
995 goto out;
996 }
997}
998
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 else if (!strcmp(args[0], "ulimit-n")) {
1000 if (global.rlimit_nofile != 0) {
1001 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001002 err_code |= ERR_ALERT;
1003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 }
1005 if (*(args[1]) == 0) {
1006 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_ALERT | ERR_FATAL;
1008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001009 }
1010 global.rlimit_nofile = atol(args[1]);
1011 }
1012 else if (!strcmp(args[0], "chroot")) {
1013 if (global.chroot != NULL) {
1014 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT;
1016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
1018 if (*(args[1]) == 0) {
1019 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 }
1023 global.chroot = strdup(args[1]);
1024 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001025 else if (!strcmp(args[0], "description")) {
1026 int i, len=0;
1027 char *d;
1028
1029 if (!*args[1]) {
1030 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1031 file, linenum, args[0]);
1032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
1034 }
1035
1036 for(i=1; *args[i]; i++)
1037 len += strlen(args[i])+1;
1038
1039 if (global.desc)
1040 free(global.desc);
1041
1042 global.desc = d = (char *)calloc(1, len);
1043
1044 d += sprintf(d, "%s", args[1]);
1045 for(i=2; *args[i]; i++)
1046 d += sprintf(d, " %s", args[i]);
1047 }
1048 else if (!strcmp(args[0], "node")) {
1049 int i;
1050 char c;
1051
1052 for (i=0; args[1][i]; i++) {
1053 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001054 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1055 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001056 break;
1057 }
1058
1059 if (!i || args[1][i]) {
1060 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1061 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1062 file, linenum, args[0]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066
1067 if (global.node)
1068 free(global.node);
1069
1070 global.node = strdup(args[1]);
1071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 else if (!strcmp(args[0], "pidfile")) {
1073 if (global.pidfile != NULL) {
1074 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 }
1083 global.pidfile = strdup(args[1]);
1084 }
Emeric Bruned760922010-10-22 17:59:25 +02001085 else if (!strcmp(args[0], "unix-bind")) {
1086 int cur_arg = 1;
1087 while (*(args[cur_arg])) {
1088 if (!strcmp(args[cur_arg], "prefix")) {
1089 if (global.unix_bind.prefix != NULL) {
1090 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1091 err_code |= ERR_ALERT;
1092 cur_arg += 2;
1093 continue;
1094 }
1095
1096 if (*(args[cur_arg+1]) == 0) {
1097 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
1100 }
1101 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1102 cur_arg += 2;
1103 continue;
1104 }
1105
1106 if (!strcmp(args[cur_arg], "mode")) {
1107
1108 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1109 cur_arg += 2;
1110 continue;
1111 }
1112
1113 if (!strcmp(args[cur_arg], "uid")) {
1114
1115 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1116 cur_arg += 2;
1117 continue;
1118 }
1119
1120 if (!strcmp(args[cur_arg], "gid")) {
1121
1122 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1123 cur_arg += 2;
1124 continue;
1125 }
1126
1127 if (!strcmp(args[cur_arg], "user")) {
1128 struct passwd *user;
1129
1130 user = getpwnam(args[cur_arg + 1]);
1131 if (!user) {
1132 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1133 file, linenum, args[0], args[cur_arg + 1 ]);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto out;
1136 }
1137
1138 global.unix_bind.ux.uid = user->pw_uid;
1139 cur_arg += 2;
1140 continue;
1141 }
1142
1143 if (!strcmp(args[cur_arg], "group")) {
1144 struct group *group;
1145
1146 group = getgrnam(args[cur_arg + 1]);
1147 if (!group) {
1148 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1149 file, linenum, args[0], args[cur_arg + 1 ]);
1150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto out;
1152 }
1153
1154 global.unix_bind.ux.gid = group->gr_gid;
1155 cur_arg += 2;
1156 continue;
1157 }
1158
Willy Tarreaub48f9582011-09-05 01:17:06 +02001159 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001160 file, linenum, args[0]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
1164 }
William Lallemand0f99e342011-10-12 17:50:54 +02001165 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1166 /* delete previous herited or defined syslog servers */
1167 struct logsrv *back;
1168 struct logsrv *tmp;
1169
1170 if (*(args[1]) != 0) {
1171 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175
1176 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1177 LIST_DEL(&tmp->list);
1178 free(tmp);
1179 }
1180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001181 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001182 struct sockaddr_storage *sk;
1183 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001184 struct logsrv *logsrv;
1185
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 if (*(args[1]) == 0 || *(args[2]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 }
William Lallemand0f99e342011-10-12 17:50:54 +02001191
1192 logsrv = calloc(1, sizeof(struct logsrv));
1193
1194 logsrv->facility = get_log_facility(args[2]);
1195 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001197 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001198 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 }
1200
William Lallemand0f99e342011-10-12 17:50:54 +02001201 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001203 logsrv->level = get_log_level(args[3]);
1204 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001207 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 }
1209 }
1210
William Lallemand0f99e342011-10-12 17:50:54 +02001211 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001212 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001213 logsrv->minlvl = get_log_level(args[4]);
1214 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001215 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001216 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001217 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001218 }
1219 }
1220
Willy Tarreau902636f2013-03-10 19:44:48 +01001221 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001222 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001223 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001225 free(logsrv);
1226 goto out;
1227 }
1228 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001229
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001230 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001231 if (port1 != port2) {
1232 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1233 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001234 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001235 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001236 goto out;
1237 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001238
William Lallemand0f99e342011-10-12 17:50:54 +02001239 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001240 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001241 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243
William Lallemand0f99e342011-10-12 17:50:54 +02001244 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001245 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001246 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1247 char *name;
1248 int len;
1249
1250 if (global.log_send_hostname != NULL) {
1251 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1252 err_code |= ERR_ALERT;
1253 goto out;
1254 }
1255
1256 if (*(args[1]))
1257 name = args[1];
1258 else
1259 name = hostname;
1260
1261 len = strlen(name);
1262
1263 /* We'll add a space after the name to respect the log format */
1264 free(global.log_send_hostname);
1265 global.log_send_hostname = malloc(len + 2);
1266 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1267 }
Kevinm48936af2010-12-22 16:08:21 +00001268 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1269 if (*(args[1]) == 0) {
1270 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
1273 }
1274 free(global.log_tag);
1275 global.log_tag = strdup(args[1]);
1276 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001277 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1278 if (global.spread_checks != 0) {
1279 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001280 err_code |= ERR_ALERT;
1281 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001282 }
1283 if (*(args[1]) == 0) {
1284 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001287 }
1288 global.spread_checks = atol(args[1]);
1289 if (global.spread_checks < 0 || global.spread_checks > 50) {
1290 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001294 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1295#ifdef USE_CPU_AFFINITY
1296 int cur_arg, i;
1297 unsigned int proc = 0;
1298 unsigned long cpus = 0;
1299
1300 if (strcmp(args[1], "all") == 0)
1301 proc = 0xFFFFFFFF;
1302 else if (strcmp(args[1], "odd") == 0)
1303 proc = 0x55555555;
1304 else if (strcmp(args[1], "even") == 0)
1305 proc = 0xAAAAAAAA;
1306 else {
1307 proc = atoi(args[1]);
1308 if (proc >= 1 && proc <= 32)
1309 proc = 1 << (proc - 1);
1310 }
1311
1312 if (!proc || !*args[2]) {
1313 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",
1314 file, linenum, args[0]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
1319 cur_arg = 2;
1320 while (*args[cur_arg]) {
1321 unsigned int low, high;
1322
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001323 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001324 char *dash = strchr(args[cur_arg], '-');
1325
1326 low = high = str2uic(args[cur_arg]);
1327 if (dash)
1328 high = str2uic(dash + 1);
1329
1330 if (high < low) {
1331 unsigned int swap = low;
1332 low = high;
1333 high = swap;
1334 }
1335
1336 if (low < 0 || high >= sizeof(long) * 8) {
1337 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1338 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1339 err_code |= ERR_ALERT | ERR_FATAL;
1340 goto out;
1341 }
1342
1343 while (low <= high)
1344 cpus |= 1UL << low++;
1345 }
1346 else {
1347 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1348 file, linenum, args[0], args[cur_arg]);
1349 err_code |= ERR_ALERT | ERR_FATAL;
1350 goto out;
1351 }
1352 cur_arg++;
1353 }
1354 for (i = 0; i < 32; i++)
1355 if (proc & (1 << i))
1356 global.cpu_map[i] = cpus;
1357#else
1358 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
1361#endif
1362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001364 struct cfg_kw_list *kwl;
1365 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001366 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001367
1368 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1369 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1370 if (kwl->kw[index].section != CFG_GLOBAL)
1371 continue;
1372 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001373 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001374 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001375 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001376 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001377 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001378 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001379 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001380 err_code |= ERR_WARN;
1381 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001382 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001384 }
1385 }
1386 }
1387
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001389 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001391
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001393 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001394 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395}
1396
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001397void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001399 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 defproxy.mode = PR_MODE_TCP;
1401 defproxy.state = PR_STNEW;
1402 defproxy.maxconn = cfg_maxpconn;
1403 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001404
Simon Horman66183002013-02-23 10:16:43 +09001405 defproxy.defsrv.check.inter = DEF_CHKINTR;
1406 defproxy.defsrv.check.fastinter = 0;
1407 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001408 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1409 defproxy.defsrv.agent.fastinter = 0;
1410 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001411 defproxy.defsrv.check.rise = DEF_RISETIME;
1412 defproxy.defsrv.check.fall = DEF_FALLTIME;
1413 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1414 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001415 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001416 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001417 defproxy.defsrv.maxqueue = 0;
1418 defproxy.defsrv.minconn = 0;
1419 defproxy.defsrv.maxconn = 0;
1420 defproxy.defsrv.slowstart = 0;
1421 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1422 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1423 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001424}
1425
Willy Tarreauade5ec42010-01-28 19:33:49 +01001426
1427static int create_cond_regex_rule(const char *file, int line,
1428 struct proxy *px, int dir, int action, int flags,
1429 const char *cmd, const char *reg, const char *repl,
1430 const char **cond_start)
1431{
1432 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001433 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001434 const char *err;
1435 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001436 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001437
1438 if (px == &defproxy) {
1439 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto err;
1442 }
1443
1444 if (*reg == 0) {
1445 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto err;
1448 }
1449
1450 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1451 err_code |= ERR_WARN;
1452
Willy Tarreau5321c422010-01-28 20:35:13 +01001453 if (cond_start &&
1454 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001455 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1456 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1457 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001458 err_code |= ERR_ALERT | ERR_FATAL;
1459 goto err;
1460 }
1461 }
1462 else if (cond_start && **cond_start) {
1463 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1464 file, line, cmd, *cond_start);
1465 err_code |= ERR_ALERT | ERR_FATAL;
1466 goto err;
1467 }
1468
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001469 err_code |= warnif_cond_conflicts(cond,
1470 (dir == SMP_OPT_DIR_REQ) ?
1471 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1472 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1473 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001474
Willy Tarreauade5ec42010-01-28 19:33:49 +01001475 preg = calloc(1, sizeof(regex_t));
1476 if (!preg) {
1477 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1478 err_code = ERR_ALERT | ERR_FATAL;
1479 goto err;
1480 }
1481
1482 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1483 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1484 err_code = ERR_ALERT | ERR_FATAL;
1485 goto err;
1486 }
1487
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001488 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001489 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001490 if (repl && err) {
1491 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1492 file, line, cmd, *err);
1493 err_code |= ERR_ALERT | ERR_FATAL;
1494 goto err;
1495 }
1496
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001497 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001498 err_code |= ERR_WARN;
1499
Willy Tarreauf4068b62012-05-08 17:37:49 +02001500 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001501 return err_code;
1502 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001503 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001504 free(preg);
1505 return err_code;
1506}
1507
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001509 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001510 * Returns the error code, 0 if OK, or any combination of :
1511 * - ERR_ABORT: must abort ASAP
1512 * - ERR_FATAL: we can continue parsing but not start the service
1513 * - ERR_WARN: a warning has been emitted
1514 * - ERR_ALERT: an alert has been emitted
1515 * Only the two first ones can stop processing, the two others are just
1516 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001517 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001518int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1519{
1520 static struct peers *curpeers = NULL;
1521 struct peer *newpeer = NULL;
1522 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001523 struct bind_conf *bind_conf;
1524 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001525 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001526 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001527
1528 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001529 if (!*args[1]) {
1530 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001531 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001532 goto out;
1533 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001534
1535 err = invalid_char(args[1]);
1536 if (err) {
1537 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1538 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001539 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001540 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001541 }
1542
1543 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1544 /*
1545 * If there are two proxies with the same name only following
1546 * combinations are allowed:
1547 */
1548 if (strcmp(curpeers->id, args[1]) == 0) {
1549 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1550 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1551 err_code |= ERR_WARN;
1552 }
1553 }
1554
1555 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1556 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1557 err_code |= ERR_ALERT | ERR_ABORT;
1558 goto out;
1559 }
1560
1561 curpeers->next = peers;
1562 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001563 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001564 curpeers->conf.line = linenum;
1565 curpeers->last_change = now.tv_sec;
1566 curpeers->id = strdup(args[1]);
1567 }
1568 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001569 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001570 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001571 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001572
1573 if (!*args[2]) {
1574 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1575 file, linenum, args[0]);
1576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
1578 }
1579
1580 err = invalid_char(args[1]);
1581 if (err) {
1582 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1583 file, linenum, *err, args[1]);
1584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
1586 }
1587
1588 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1590 err_code |= ERR_ALERT | ERR_ABORT;
1591 goto out;
1592 }
1593
1594 /* the peers are linked backwards first */
1595 curpeers->count++;
1596 newpeer->next = curpeers->remote;
1597 curpeers->remote = newpeer;
1598 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001599 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001600 newpeer->conf.line = linenum;
1601
1602 newpeer->last_change = now.tv_sec;
1603 newpeer->id = strdup(args[1]);
1604
Willy Tarreau902636f2013-03-10 19:44:48 +01001605 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001606 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001607 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001608 err_code |= ERR_ALERT | ERR_FATAL;
1609 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001611
1612 proto = protocol_by_family(sk->ss_family);
1613 if (!proto || !proto->connect) {
1614 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1615 file, linenum, args[0], args[1]);
1616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
1618 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001619
1620 if (port1 != port2) {
1621 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1622 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
1625 }
1626
Willy Tarreau2aa38802013-02-20 19:20:59 +01001627 if (!port1) {
1628 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1629 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
1632 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001633
Emeric Brun32da3c42010-09-23 18:39:19 +02001634 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001635 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001636 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001637 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001638
Emeric Brun32da3c42010-09-23 18:39:19 +02001639 if (strcmp(newpeer->id, localpeer) == 0) {
1640 /* Current is local peer, it define a frontend */
1641 newpeer->local = 1;
1642
1643 if (!curpeers->peers_fe) {
1644 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1645 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1646 err_code |= ERR_ALERT | ERR_ABORT;
1647 goto out;
1648 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001649
Willy Tarreau237250c2011-07-29 01:49:03 +02001650 init_new_proxy(curpeers->peers_fe);
1651 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001652
1653 curpeers->peers_fe->last_change = now.tv_sec;
1654 curpeers->peers_fe->id = strdup(args[1]);
1655 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001656 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001657 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1658 curpeers->peers_fe->timeout.connect = 5000;
1659 curpeers->peers_fe->accept = peer_accept;
1660 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001661 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1662 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001663
1664 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1665
Willy Tarreau902636f2013-03-10 19:44:48 +01001666 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1667 if (errmsg && *errmsg) {
1668 indent_msg(&errmsg, 2);
1669 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001670 }
1671 else
1672 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1673 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001674 err_code |= ERR_FATAL;
1675 goto out;
1676 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001677
1678 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1679 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1680 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1681 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1682 l->accept = session_accept;
1683 l->handler = process_session;
1684 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1685 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1686 global.maxsock += l->maxconn;
1687 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001688 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001689 else {
1690 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1691 file, linenum, args[0], args[1],
1692 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1693 err_code |= ERR_FATAL;
1694 goto out;
1695 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001696 }
1697 } /* neither "peer" nor "peers" */
1698 else if (*args[0] != 0) {
1699 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703
1704out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001705 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001706 return err_code;
1707}
1708
Willy Tarreau3842f002009-06-14 11:39:52 +02001709int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710{
1711 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001712 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001713 int rc;
1714 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001715 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001716 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001717 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001718 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001719 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720
Willy Tarreau977b8e42006-12-29 14:19:17 +01001721 if (!strcmp(args[0], "listen"))
1722 rc = PR_CAP_LISTEN;
1723 else if (!strcmp(args[0], "frontend"))
1724 rc = PR_CAP_FE | PR_CAP_RS;
1725 else if (!strcmp(args[0], "backend"))
1726 rc = PR_CAP_BE | PR_CAP_RS;
1727 else if (!strcmp(args[0], "ruleset"))
1728 rc = PR_CAP_RS;
1729 else
1730 rc = PR_CAP_NONE;
1731
1732 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001733 struct ebpt_node *node;
1734
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735 if (!*args[1]) {
1736 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1737 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1738 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001739 err_code |= ERR_ALERT | ERR_ABORT;
1740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001742
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001743 err = invalid_char(args[1]);
1744 if (err) {
1745 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1746 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001747 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001748 }
1749
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001750 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1751 curproxy = container_of(node, struct proxy, conf.by_name);
1752
1753 if (strcmp(curproxy->id, args[1]) != 0)
1754 break;
1755
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001756 /*
1757 * If there are two proxies with the same name only following
1758 * combinations are allowed:
1759 *
1760 * listen backend frontend ruleset
1761 * listen - - - -
1762 * backend - - OK -
1763 * frontend - OK - -
1764 * ruleset - - - -
1765 */
1766
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001767 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1768 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001769 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1770 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1771 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001773 }
1774 }
1775
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1777 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001778 err_code |= ERR_ALERT | ERR_ABORT;
1779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001781
Willy Tarreau97cb7802010-01-03 20:23:58 +01001782 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 curproxy->next = proxy;
1784 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001785 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1786 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001787 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001789 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001790 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791
1792 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001794 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001795
Willy Tarreau4348fad2012-09-20 16:48:07 +02001796 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1797
Willy Tarreau902636f2013-03-10 19:44:48 +01001798 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1799 if (errmsg && *errmsg) {
1800 indent_msg(&errmsg, 2);
1801 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001802 }
1803 else
1804 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1805 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001806 err_code |= ERR_FATAL;
1807 goto out;
1808 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001809
Willy Tarreau4348fad2012-09-20 16:48:07 +02001810 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001811 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 }
1814
1815 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001816 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001817 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001818
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001821 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001822 curproxy->no_options = defproxy.no_options;
1823 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001824 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001825 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001826 curproxy->except_net = defproxy.except_net;
1827 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001828 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001829 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001831 if (defproxy.fwdfor_hdr_len) {
1832 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1833 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1834 }
1835
Willy Tarreaub86db342009-11-30 11:50:16 +01001836 if (defproxy.orgto_hdr_len) {
1837 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1838 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1839 }
1840
Mark Lamourinec2247f02012-01-04 13:02:01 -05001841 if (defproxy.server_id_hdr_len) {
1842 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1843 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1844 }
1845
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 if (curproxy->cap & PR_CAP_FE) {
1847 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001848 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001849 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001850
1851 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001852 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1853 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854
1855 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857
Willy Tarreau977b8e42006-12-29 14:19:17 +01001858 if (curproxy->cap & PR_CAP_BE) {
1859 curproxy->fullconn = defproxy.fullconn;
1860 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001862 if (defproxy.check_req) {
1863 curproxy->check_req = calloc(1, defproxy.check_len);
1864 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1865 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001866 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001867
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001868 if (defproxy.expect_str) {
1869 curproxy->expect_str = strdup(defproxy.expect_str);
1870 if (defproxy.expect_regex) {
1871 /* note: this regex is known to be valid */
1872 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1873 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1874 }
1875 }
1876
Willy Tarreau67402132012-05-31 20:40:20 +02001877 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001878 if (defproxy.cookie_name)
1879 curproxy->cookie_name = strdup(defproxy.cookie_name);
1880 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001881 if (defproxy.cookie_domain)
1882 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001883
Willy Tarreau31936852010-10-06 16:59:56 +02001884 if (defproxy.cookie_maxidle)
1885 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1886
1887 if (defproxy.cookie_maxlife)
1888 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1889
Emeric Brun647caf12009-06-30 17:57:00 +02001890 if (defproxy.rdp_cookie_name)
1891 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1892 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1893
Willy Tarreau01732802007-11-01 22:48:15 +01001894 if (defproxy.url_param_name)
1895 curproxy->url_param_name = strdup(defproxy.url_param_name);
1896 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001897
Benoitaffb4812009-03-25 13:02:10 +01001898 if (defproxy.hh_name)
1899 curproxy->hh_name = strdup(defproxy.hh_name);
1900 curproxy->hh_len = defproxy.hh_len;
1901 curproxy->hh_match_domain = defproxy.hh_match_domain;
1902
Willy Tarreauef9a3602012-12-08 22:29:20 +01001903 if (defproxy.conn_src.iface_name)
1904 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1905 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001906 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001907#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001908 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001909#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001912 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913 if (defproxy.capture_name)
1914 curproxy->capture_name = strdup(defproxy.capture_name);
1915 curproxy->capture_namelen = defproxy.capture_namelen;
1916 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918
Willy Tarreau977b8e42006-12-29 14:19:17 +01001919 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001920 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001921 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001922 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001923 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001924 curproxy->uri_auth = defproxy.uri_auth;
1925 curproxy->mon_net = defproxy.mon_net;
1926 curproxy->mon_mask = defproxy.mon_mask;
1927 if (defproxy.monitor_uri)
1928 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1929 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001930 if (defproxy.defbe.name)
1931 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001932
1933 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001934 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1935 if (curproxy->conf.logformat_string &&
1936 curproxy->conf.logformat_string != default_http_log_format &&
1937 curproxy->conf.logformat_string != default_tcp_log_format &&
1938 curproxy->conf.logformat_string != clf_http_log_format)
1939 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1940
1941 if (defproxy.conf.lfs_file) {
1942 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1943 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001945 }
1946
1947 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001948 curproxy->timeout.connect = defproxy.timeout.connect;
1949 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001950 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001951 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001952 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001953 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001954 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001955 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001956 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957 }
1958
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001960
1961 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001962 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001963 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001964 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001965 LIST_INIT(&node->list);
1966 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1967 }
1968
Willy Tarreau62a61232013-04-12 18:13:46 +02001969 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1970 if (curproxy->conf.uniqueid_format_string)
1971 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1972
1973 if (defproxy.conf.uif_file) {
1974 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1975 curproxy->conf.uif_line = defproxy.conf.uif_line;
1976 }
William Lallemanda73203e2012-03-12 12:48:57 +01001977
1978 /* copy default header unique id */
1979 if (defproxy.header_unique_id)
1980 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1981
William Lallemand82fe75c2012-10-23 10:25:10 +02001982 /* default compression options */
1983 if (defproxy.comp != NULL) {
1984 curproxy->comp = calloc(1, sizeof(struct comp));
1985 curproxy->comp->algos = defproxy.comp->algos;
1986 curproxy->comp->types = defproxy.comp->types;
1987 }
1988
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001990 curproxy->conf.used_listener_id = EB_ROOT;
1991 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001992
Willy Tarreau93893792009-07-23 13:19:11 +02001993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 }
1995 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1996 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001997 /* FIXME-20070101: we should do this too at the end of the
1998 * config parsing to free all default values.
1999 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002000 free(defproxy.check_req);
2001 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002002 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002003 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002004 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002005 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002006 free(defproxy.capture_name);
2007 free(defproxy.monitor_uri);
2008 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002009 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002010 free(defproxy.fwdfor_hdr_name);
2011 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002012 free(defproxy.orgto_hdr_name);
2013 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002014 free(defproxy.server_id_hdr_name);
2015 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002016 free(defproxy.expect_str);
2017 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002018
Willy Tarreau62a61232013-04-12 18:13:46 +02002019 if (defproxy.conf.logformat_string != default_http_log_format &&
2020 defproxy.conf.logformat_string != default_tcp_log_format &&
2021 defproxy.conf.logformat_string != clf_http_log_format)
2022 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002023
Willy Tarreau62a61232013-04-12 18:13:46 +02002024 free(defproxy.conf.uniqueid_format_string);
2025 free(defproxy.conf.lfs_file);
2026 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002027
Willy Tarreaua534fea2008-08-03 12:19:50 +02002028 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002029 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002030
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 /* we cannot free uri_auth because it might already be used */
2032 init_default_instance();
2033 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002034 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2035 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002036 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 }
2039 else if (curproxy == NULL) {
2040 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002044
2045 /* update the current file and line being parsed */
2046 curproxy->conf.args.file = curproxy->conf.file;
2047 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048
2049 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002050 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2051 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2052 if (err_code & ERR_FATAL)
2053 goto out;
2054 }
2055 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002056 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002057 int cur_arg;
2058
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 if (curproxy == &defproxy) {
2060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066
Willy Tarreau24709282013-03-10 21:32:12 +01002067 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002068 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002073
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002074 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002075
2076 /* use default settings for unix sockets */
2077 bind_conf->ux.uid = global.unix_bind.ux.uid;
2078 bind_conf->ux.gid = global.unix_bind.ux.gid;
2079 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002080
2081 /* NOTE: the following line might create several listeners if there
2082 * are comma-separated IPs or port ranges. So all further processing
2083 * will have to be applied to all listeners created after last_listen.
2084 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002085 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2086 if (errmsg && *errmsg) {
2087 indent_msg(&errmsg, 2);
2088 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002089 }
2090 else
2091 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2092 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
2095 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002096
Willy Tarreau4348fad2012-09-20 16:48:07 +02002097 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2098 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002099 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002100 }
2101
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002102 cur_arg = 2;
2103 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002104 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002105 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002106 char *err;
2107
Willy Tarreau26982662012-09-12 23:17:10 +02002108 kw = bind_find_kw(args[cur_arg]);
2109 if (kw) {
2110 char *err = NULL;
2111 int code;
2112
2113 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002114 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2115 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002116 cur_arg += 1 + kw->skip ;
2117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
2119 }
2120
Willy Tarreau4348fad2012-09-20 16:48:07 +02002121 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002122 err_code |= code;
2123
2124 if (code) {
2125 if (err && *err) {
2126 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002127 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002128 }
2129 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002130 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2131 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002132 if (code & ERR_FATAL) {
2133 free(err);
2134 cur_arg += 1 + kw->skip;
2135 goto out;
2136 }
2137 }
2138 free(err);
2139 cur_arg += 1 + kw->skip;
2140 continue;
2141 }
2142
Willy Tarreau8638f482012-09-18 18:01:17 +02002143 err = NULL;
2144 if (!bind_dumped) {
2145 bind_dump_kws(&err);
2146 indent_msg(&err, 4);
2147 bind_dumped = 1;
2148 }
2149
2150 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2151 file, linenum, args[0], args[1], args[cur_arg],
2152 err ? " Registered keywords :" : "", err ? err : "");
2153 free(err);
2154
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002157 }
Willy Tarreau93893792009-07-23 13:19:11 +02002158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 }
2160 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002161 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2163 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002166 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002167 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002168 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002169
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 /* flush useless bits */
2171 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002174 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002175 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002177
Willy Tarreau1c47f852006-07-09 08:22:27 +02002178 if (!*args[1]) {
2179 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002183 }
2184
Willy Tarreaua534fea2008-08-03 12:19:50 +02002185 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002186 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002187 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002188 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002189 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2190
Willy Tarreau93893792009-07-23 13:19:11 +02002191 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2194 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2195 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2196 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2197 else {
2198 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 }
2202 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002203 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002204 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002205
2206 if (curproxy == &defproxy) {
2207 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2208 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002211 }
2212
2213 if (!*args[1]) {
2214 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002218 }
2219
2220 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002221 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002222
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002223 if (curproxy->uuid <= 0) {
2224 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002225 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_ALERT | ERR_FATAL;
2227 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002228 }
2229
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002230 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2231 if (node) {
2232 struct proxy *target = container_of(node, struct proxy, conf.id);
2233 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2234 file, linenum, proxy_type_str(curproxy), curproxy->id,
2235 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002240 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002241 else if (!strcmp(args[0], "description")) {
2242 int i, len=0;
2243 char *d;
2244
Cyril Bonté99ed3272010-01-24 23:29:44 +01002245 if (curproxy == &defproxy) {
2246 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2247 file, linenum, args[0]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002252 if (!*args[1]) {
2253 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2254 file, linenum, args[0]);
2255 return -1;
2256 }
2257
2258 for(i=1; *args[i]; i++)
2259 len += strlen(args[i])+1;
2260
2261 d = (char *)calloc(1, len);
2262 curproxy->desc = d;
2263
2264 d += sprintf(d, "%s", args[1]);
2265 for(i=2; *args[i]; i++)
2266 d += sprintf(d, " %s", args[i]);
2267
2268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2270 curproxy->state = PR_STSTOPPED;
2271 }
2272 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2273 curproxy->state = PR_STNEW;
2274 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002275 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2276 int cur_arg = 1;
2277 unsigned int set = 0;
2278
2279 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002280 unsigned int low, high;
2281
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002282 if (strcmp(args[cur_arg], "all") == 0) {
2283 set = 0;
2284 break;
2285 }
2286 else if (strcmp(args[cur_arg], "odd") == 0) {
2287 set |= 0x55555555;
2288 }
2289 else if (strcmp(args[cur_arg], "even") == 0) {
2290 set |= 0xAAAAAAAA;
2291 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002292 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002293 char *dash = strchr(args[cur_arg], '-');
2294
2295 low = high = str2uic(args[cur_arg]);
2296 if (dash)
2297 high = str2uic(dash + 1);
2298
2299 if (high < low) {
2300 unsigned int swap = low;
2301 low = high;
2302 high = swap;
2303 }
2304
2305 if (low < 1 || high > 32) {
2306 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002310 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002311
2312 if (high > global.nbproc) {
2313 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2314 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002316 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002317 while (low <= high)
2318 set |= 1 << (low++ - 1);
2319 }
2320 else {
2321 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2322 file, linenum, args[0]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002325 }
2326 cur_arg++;
2327 }
2328 curproxy->bind_proc = set;
2329 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002330 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002331 if (curproxy == &defproxy) {
2332 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002335 }
2336
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002337 err = invalid_char(args[1]);
2338 if (err) {
2339 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2340 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002341 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002342 }
2343
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002344 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002345 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2346 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002349 }
2350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2352 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353
Willy Tarreau977b8e42006-12-29 14:19:17 +01002354 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002356
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 if (*(args[1]) == 0) {
2358 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002363
Willy Tarreau67402132012-05-31 20:40:20 +02002364 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002365 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002366 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002367 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 curproxy->cookie_name = strdup(args[1]);
2369 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002370
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 cur_arg = 2;
2372 while (*(args[cur_arg])) {
2373 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002374 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
2376 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002377 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002380 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
2382 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002383 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002386 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002388 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002389 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002392 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002394 else if (!strcmp(args[cur_arg], "httponly")) {
2395 curproxy->ck_opts |= PR_CK_HTTPONLY;
2396 }
2397 else if (!strcmp(args[cur_arg], "secure")) {
2398 curproxy->ck_opts |= PR_CK_SECURE;
2399 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002400 else if (!strcmp(args[cur_arg], "domain")) {
2401 if (!*args[cur_arg + 1]) {
2402 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2403 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002406 }
2407
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002408 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002409 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002410 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2411 " dots nor does not start with a dot."
2412 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002413 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002414 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002415 }
2416
2417 err = invalid_domainchar(args[cur_arg + 1]);
2418 if (err) {
2419 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2420 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002423 }
2424
Willy Tarreau68a897b2009-12-03 23:28:34 +01002425 if (!curproxy->cookie_domain) {
2426 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2427 } else {
2428 /* one domain was already specified, add another one by
2429 * building the string which will be returned along with
2430 * the cookie.
2431 */
2432 char *new_ptr;
2433 int new_len = strlen(curproxy->cookie_domain) +
2434 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2435 new_ptr = malloc(new_len);
2436 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2437 free(curproxy->cookie_domain);
2438 curproxy->cookie_domain = new_ptr;
2439 }
Willy Tarreau31936852010-10-06 16:59:56 +02002440 cur_arg++;
2441 }
2442 else if (!strcmp(args[cur_arg], "maxidle")) {
2443 unsigned int maxidle;
2444 const char *res;
2445
2446 if (!*args[cur_arg + 1]) {
2447 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2448 file, linenum, args[cur_arg]);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452
2453 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2454 if (res) {
2455 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2456 file, linenum, *res, args[cur_arg]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460 curproxy->cookie_maxidle = maxidle;
2461 cur_arg++;
2462 }
2463 else if (!strcmp(args[cur_arg], "maxlife")) {
2464 unsigned int maxlife;
2465 const char *res;
2466
2467 if (!*args[cur_arg + 1]) {
2468 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2469 file, linenum, args[cur_arg]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
2474 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2475 if (res) {
2476 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2477 file, linenum, *res, args[cur_arg]);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002482 cur_arg++;
2483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002485 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 +02002486 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
2490 cur_arg++;
2491 }
Willy Tarreau67402132012-05-31 20:40:20 +02002492 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2494 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 }
2497
Willy Tarreau67402132012-05-31 20:40:20 +02002498 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2500 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002501 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002503
Willy Tarreau67402132012-05-31 20:40:20 +02002504 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002505 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2506 file, linenum);
2507 err_code |= ERR_ALERT | ERR_FATAL;
2508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002510 else if (!strcmp(args[0], "persist")) { /* persist */
2511 if (*(args[1]) == 0) {
2512 Alert("parsing [%s:%d] : missing persist method.\n",
2513 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002516 }
2517
2518 if (!strncmp(args[1], "rdp-cookie", 10)) {
2519 curproxy->options2 |= PR_O2_RDPC_PRST;
2520
Emeric Brunb982a3d2010-01-04 15:45:53 +01002521 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002522 const char *beg, *end;
2523
2524 beg = args[1] + 11;
2525 end = strchr(beg, ')');
2526
2527 if (!end || end == beg) {
2528 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2529 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002532 }
2533
2534 free(curproxy->rdp_cookie_name);
2535 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2536 curproxy->rdp_cookie_len = end-beg;
2537 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002538 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002539 free(curproxy->rdp_cookie_name);
2540 curproxy->rdp_cookie_name = strdup("msts");
2541 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2542 }
2543 else { /* syntax */
2544 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2545 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002548 }
2549 }
2550 else {
2551 Alert("parsing [%s:%d] : unknown persist method.\n",
2552 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002555 }
2556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002558 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002560 if (curproxy == &defproxy) {
2561 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
2564 }
2565
Willy Tarreau977b8e42006-12-29 14:19:17 +01002566 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002570 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002576 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 curproxy->appsession_name = strdup(args[1]);
2578 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2579 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002580 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2581 if (err) {
2582 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2583 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002586 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002587 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002588
Willy Tarreau51041c72007-09-09 21:56:53 +02002589 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2590 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_ABORT;
2592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002594
2595 cur_arg = 6;
2596 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002597 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2598 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002599 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002600 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002601 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002602 } else if (!strcmp(args[cur_arg], "prefix")) {
2603 curproxy->options2 |= PR_O2_AS_PFX;
2604 } else if (!strcmp(args[cur_arg], "mode")) {
2605 if (!*args[cur_arg + 1]) {
2606 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2607 file, linenum, args[0], args[cur_arg]);
2608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
2610 }
2611
2612 cur_arg++;
2613 if (!strcmp(args[cur_arg], "query-string")) {
2614 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2615 curproxy->options2 |= PR_O2_AS_M_QS;
2616 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2617 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2618 curproxy->options2 |= PR_O2_AS_M_PP;
2619 } else {
2620 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
2623 }
2624 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002625 cur_arg++;
2626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 } /* Url App Session */
2628 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002629 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002631
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002633 if (curproxy == &defproxy) {
2634 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637 }
2638
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 if (*(args[4]) == 0) {
2640 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002645 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 curproxy->capture_name = strdup(args[2]);
2647 curproxy->capture_namelen = strlen(curproxy->capture_name);
2648 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 curproxy->to_log |= LW_COOKIE;
2650 }
2651 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2652 struct cap_hdr *hdr;
2653
2654 if (curproxy == &defproxy) {
2655 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 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 }
2659
2660 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2661 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2662 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 }
2666
2667 hdr = calloc(sizeof(struct cap_hdr), 1);
2668 hdr->next = curproxy->req_cap;
2669 hdr->name = strdup(args[3]);
2670 hdr->namelen = strlen(args[3]);
2671 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002672 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 hdr->index = curproxy->nb_req_cap++;
2674 curproxy->req_cap = hdr;
2675 curproxy->to_log |= LW_REQHDR;
2676 }
2677 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2678 struct cap_hdr *hdr;
2679
2680 if (curproxy == &defproxy) {
2681 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 +02002682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
2685
2686 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2687 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2688 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692 hdr = calloc(sizeof(struct cap_hdr), 1);
2693 hdr->next = curproxy->rsp_cap;
2694 hdr->name = strdup(args[3]);
2695 hdr->namelen = strlen(args[3]);
2696 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002697 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 hdr->index = curproxy->nb_rsp_cap++;
2699 curproxy->rsp_cap = hdr;
2700 curproxy->to_log |= LW_RSPHDR;
2701 }
2702 else {
2703 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2704 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 }
2708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002711 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002712
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 if (*(args[1]) == 0) {
2714 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 }
2719 curproxy->conn_retries = atol(args[1]);
2720 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002721 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002722 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002723
2724 if (curproxy == &defproxy) {
2725 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
2728 }
2729
Willy Tarreau20b0de52012-12-24 15:45:22 +01002730 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2731 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2732 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2733 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002734 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002735 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2736 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 +01002737 file, linenum, args[0]);
2738 err_code |= ERR_WARN;
2739 }
2740
Willy Tarreauff011f22011-01-06 17:51:27 +01002741 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002742
Willy Tarreauff011f22011-01-06 17:51:27 +01002743 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002744 err_code |= ERR_ALERT | ERR_ABORT;
2745 goto out;
2746 }
2747
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002748 err_code |= warnif_cond_conflicts(rule->cond,
2749 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2750 file, linenum);
2751
Willy Tarreauff011f22011-01-06 17:51:27 +01002752 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002753 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002754 else if (!strcmp(args[0], "http-response")) { /* response access control */
2755 struct http_res_rule *rule;
2756
2757 if (curproxy == &defproxy) {
2758 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762
2763 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2764 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2765 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2766 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2767 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2768 file, linenum, args[0]);
2769 err_code |= ERR_WARN;
2770 }
2771
2772 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2773
2774 if (!rule) {
2775 err_code |= ERR_ALERT | ERR_ABORT;
2776 goto out;
2777 }
2778
2779 err_code |= warnif_cond_conflicts(rule->cond,
2780 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2781 file, linenum);
2782
2783 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2784 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002785 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2786 /* set the header name and length into the proxy structure */
2787 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2788 err_code |= ERR_WARN;
2789
2790 if (!*args[1]) {
2791 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2792 file, linenum, args[0]);
2793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
2795 }
2796
2797 /* set the desired header name */
2798 free(curproxy->server_id_hdr_name);
2799 curproxy->server_id_hdr_name = strdup(args[1]);
2800 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2801 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002802 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002803 if (curproxy == &defproxy) {
2804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002807 }
2808
Willy Tarreauef6494c2010-01-28 17:12:36 +01002809 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002810 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2811 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002814 }
2815
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002816 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2817 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2818 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002821 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002822
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002823 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002824 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002825 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002826 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002827 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002828
Cyril Bonté99ed3272010-01-24 23:29:44 +01002829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002835 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002836 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2837 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002840 }
2841
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002842 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002843 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002844 err_code |= warnif_cond_conflicts(rule->cond,
2845 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2846 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002847 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002848 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002849 struct switching_rule *rule;
2850
Willy Tarreaub099aca2008-10-12 17:26:37 +02002851 if (curproxy == &defproxy) {
2852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002855 }
2856
Willy Tarreau55ea7572007-06-17 19:56:27 +02002857 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002859
2860 if (*(args[1]) == 0) {
2861 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002864 }
2865
Willy Tarreauef6494c2010-01-28 17:12:36 +01002866 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002867 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002871 }
2872
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002873 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2874 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2875 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002878 }
2879
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002880 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002881
Willy Tarreau55ea7572007-06-17 19:56:27 +02002882 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2883 rule->cond = cond;
2884 rule->be.name = strdup(args[1]);
2885 LIST_INIT(&rule->list);
2886 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2887 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002888 else if (strcmp(args[0], "use-server") == 0) {
2889 struct server_rule *rule;
2890
2891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2898 err_code |= ERR_WARN;
2899
2900 if (*(args[1]) == 0) {
2901 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905
2906 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2907 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2908 file, linenum, args[0]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002913 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2914 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2915 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002920 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002921
2922 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2923 rule->cond = cond;
2924 rule->srv.name = strdup(args[1]);
2925 LIST_INIT(&rule->list);
2926 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2927 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2928 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002929 else if ((!strcmp(args[0], "force-persist")) ||
2930 (!strcmp(args[0], "ignore-persist"))) {
2931 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002932
2933 if (curproxy == &defproxy) {
2934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2940 err_code |= ERR_WARN;
2941
Willy Tarreauef6494c2010-01-28 17:12:36 +01002942 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002943 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2944 file, linenum, args[0]);
2945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
2947 }
2948
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002949 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2950 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2951 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
2954 }
2955
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002956 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2957 * where force-persist is applied.
2958 */
2959 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002960
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002961 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002962 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002963 if (!strcmp(args[0], "force-persist")) {
2964 rule->type = PERSIST_TYPE_FORCE;
2965 } else {
2966 rule->type = PERSIST_TYPE_IGNORE;
2967 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002968 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002969 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002970 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002971 else if (!strcmp(args[0], "stick-table")) {
2972 int myidx = 1;
2973
Emeric Brun32da3c42010-09-23 18:39:19 +02002974 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002975 curproxy->table.type = (unsigned int)-1;
2976 while (*args[myidx]) {
2977 const char *err;
2978
2979 if (strcmp(args[myidx], "size") == 0) {
2980 myidx++;
2981 if (!*(args[myidx])) {
2982 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2983 file, linenum, args[myidx-1]);
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2988 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2989 file, linenum, *err, args[myidx-1]);
2990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
2992 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002993 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002994 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002995 else if (strcmp(args[myidx], "peers") == 0) {
2996 myidx++;
Godbach50523162013-12-11 19:48:57 +08002997 if (!*(args[myidx])) {
2998 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2999 file, linenum, args[myidx-1]);
3000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
3002 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003003 curproxy->table.peers.name = strdup(args[myidx++]);
3004 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003005 else if (strcmp(args[myidx], "expire") == 0) {
3006 myidx++;
3007 if (!*(args[myidx])) {
3008 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3009 file, linenum, args[myidx-1]);
3010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
3012 }
3013 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3014 if (err) {
3015 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3016 file, linenum, *err, args[myidx-1]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003021 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003022 }
3023 else if (strcmp(args[myidx], "nopurge") == 0) {
3024 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003025 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003026 }
3027 else if (strcmp(args[myidx], "type") == 0) {
3028 myidx++;
3029 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3030 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3031 file, linenum, args[myidx]);
3032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
3034 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003035 /* myidx already points to next arg */
3036 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003037 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003038 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003039 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003040
3041 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003042 nw = args[myidx];
3043 while (*nw) {
3044 /* the "store" keyword supports a comma-separated list */
3045 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003046 sa = NULL; /* store arg */
3047 while (*nw && *nw != ',') {
3048 if (*nw == '(') {
3049 *nw = 0;
3050 sa = ++nw;
3051 while (*nw != ')') {
3052 if (!*nw) {
3053 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3054 file, linenum, args[0], cw);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058 nw++;
3059 }
3060 *nw = '\0';
3061 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003062 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003063 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003064 if (*nw)
3065 *nw++ = '\0';
3066 type = stktable_get_data_type(cw);
3067 if (type < 0) {
3068 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3069 file, linenum, args[0], cw);
3070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
3072 }
Willy Tarreauac782882010-06-20 10:41:54 +02003073
3074 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3075 switch (err) {
3076 case PE_NONE: break;
3077 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003078 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3079 file, linenum, args[0], cw);
3080 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003081 break;
3082
3083 case PE_ARG_MISSING:
3084 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3085 file, linenum, args[0], cw);
3086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
3088
3089 case PE_ARG_NOT_USED:
3090 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3091 file, linenum, args[0], cw);
3092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
3094
3095 default:
3096 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3097 file, linenum, args[0], cw);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003100 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003101 }
3102 myidx++;
3103 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003104 else {
3105 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3106 file, linenum, args[myidx]);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003109 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003110 }
3111
3112 if (!curproxy->table.size) {
3113 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3114 file, linenum);
3115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
3117 }
3118
3119 if (curproxy->table.type == (unsigned int)-1) {
3120 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3121 file, linenum);
3122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
3124 }
3125 }
3126 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003127 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003128 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003129 int myidx = 0;
3130 const char *name = NULL;
3131 int flags;
3132
3133 if (curproxy == &defproxy) {
3134 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
3139 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3140 err_code |= ERR_WARN;
3141 goto out;
3142 }
3143
3144 myidx++;
3145 if ((strcmp(args[myidx], "store") == 0) ||
3146 (strcmp(args[myidx], "store-request") == 0)) {
3147 myidx++;
3148 flags = STK_IS_STORE;
3149 }
3150 else if (strcmp(args[myidx], "store-response") == 0) {
3151 myidx++;
3152 flags = STK_IS_STORE | STK_ON_RSP;
3153 }
3154 else if (strcmp(args[myidx], "match") == 0) {
3155 myidx++;
3156 flags = STK_IS_MATCH;
3157 }
3158 else if (strcmp(args[myidx], "on") == 0) {
3159 myidx++;
3160 flags = STK_IS_MATCH | STK_IS_STORE;
3161 }
3162 else {
3163 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
3166 }
3167
3168 if (*(args[myidx]) == 0) {
3169 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
3172 }
3173
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003174 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003175 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003176 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003177 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
3180 }
3181
3182 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003183 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3184 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3185 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003186 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003187 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003188 goto out;
3189 }
3190 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003191 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3192 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3193 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003194 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003195 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003196 goto out;
3197 }
3198 }
3199
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003200 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003201 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003202
Emeric Brunb982a3d2010-01-04 15:45:53 +01003203 if (strcmp(args[myidx], "table") == 0) {
3204 myidx++;
3205 name = args[myidx++];
3206 }
3207
Willy Tarreauef6494c2010-01-28 17:12:36 +01003208 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003209 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3210 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3211 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003212 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003213 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003214 goto out;
3215 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003216 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003217 else if (*(args[myidx])) {
3218 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3219 file, linenum, args[0], args[myidx]);
3220 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003221 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003222 goto out;
3223 }
Emeric Brun97679e72010-09-23 17:56:44 +02003224 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003225 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003226 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003227 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003228
Emeric Brunb982a3d2010-01-04 15:45:53 +01003229 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3230 rule->cond = cond;
3231 rule->expr = expr;
3232 rule->flags = flags;
3233 rule->table.name = name ? strdup(name) : NULL;
3234 LIST_INIT(&rule->list);
3235 if (flags & STK_ON_RSP)
3236 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3237 else
3238 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003241 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003243
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3245 curproxy->uri_auth = NULL; /* we must detach from the default config */
3246
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003247 if (!*args[1]) {
3248 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003249 } else if (!strcmp(args[1], "admin")) {
3250 struct stats_admin_rule *rule;
3251
3252 if (curproxy == &defproxy) {
3253 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
3256 }
3257
3258 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3259 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3260 err_code |= ERR_ALERT | ERR_ABORT;
3261 goto out;
3262 }
3263
3264 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3265 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3266 file, linenum, args[0], args[1]);
3267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
3269 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003270 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3271 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3272 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
3275 }
3276
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003277 err_code |= warnif_cond_conflicts(cond,
3278 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3279 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003280
3281 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3282 rule->cond = cond;
3283 LIST_INIT(&rule->list);
3284 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 } else if (!strcmp(args[1], "uri")) {
3286 if (*(args[2]) == 0) {
3287 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3291 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
3295 } else if (!strcmp(args[1], "realm")) {
3296 if (*(args[2]) == 0) {
3297 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_ALERT | ERR_ABORT;
3303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003305 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003306 unsigned interval;
3307
3308 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3309 if (err) {
3310 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3311 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003314 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3315 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_ABORT;
3317 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003318 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003319 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003320 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003321
3322 if (curproxy == &defproxy) {
3323 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326 }
3327
3328 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3329 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3330 err_code |= ERR_ALERT | ERR_ABORT;
3331 goto out;
3332 }
3333
Willy Tarreauff011f22011-01-06 17:51:27 +01003334 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3335 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003336 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3337 file, linenum, args[0]);
3338 err_code |= ERR_WARN;
3339 }
3340
Willy Tarreauff011f22011-01-06 17:51:27 +01003341 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003342
Willy Tarreauff011f22011-01-06 17:51:27 +01003343 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003344 err_code |= ERR_ALERT | ERR_ABORT;
3345 goto out;
3346 }
3347
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003348 err_code |= warnif_cond_conflicts(rule->cond,
3349 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3350 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003351 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003352
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 } else if (!strcmp(args[1], "auth")) {
3354 if (*(args[2]) == 0) {
3355 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_ABORT;
3361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
3363 } else if (!strcmp(args[1], "scope")) {
3364 if (*(args[2]) == 0) {
3365 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3369 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003370 err_code |= ERR_ALERT | ERR_ABORT;
3371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
3373 } else if (!strcmp(args[1], "enable")) {
3374 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3375 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_ABORT;
3377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003379 } else if (!strcmp(args[1], "hide-version")) {
3380 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003382 err_code |= ERR_ALERT | ERR_ABORT;
3383 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003384 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003385 } else if (!strcmp(args[1], "show-legends")) {
3386 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3387 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3388 err_code |= ERR_ALERT | ERR_ABORT;
3389 goto out;
3390 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003391 } else if (!strcmp(args[1], "show-node")) {
3392
3393 if (*args[2]) {
3394 int i;
3395 char c;
3396
3397 for (i=0; args[2][i]; i++) {
3398 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003399 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3400 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003401 break;
3402 }
3403
3404 if (!i || args[2][i]) {
3405 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3406 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3407 file, linenum, args[0], args[1]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
3411 }
3412
3413 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3414 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3415 err_code |= ERR_ALERT | ERR_ABORT;
3416 goto out;
3417 }
3418 } else if (!strcmp(args[1], "show-desc")) {
3419 char *desc = NULL;
3420
3421 if (*args[2]) {
3422 int i, len=0;
3423 char *d;
3424
3425 for(i=2; *args[i]; i++)
3426 len += strlen(args[i])+1;
3427
3428 desc = d = (char *)calloc(1, len);
3429
3430 d += sprintf(d, "%s", args[2]);
3431 for(i=3; *args[i]; i++)
3432 d += sprintf(d, " %s", args[i]);
3433 }
3434
3435 if (!*args[2] && !global.desc)
3436 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3437 file, linenum, args[1]);
3438 else {
3439 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3440 free(desc);
3441 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3442 err_code |= ERR_ALERT | ERR_ABORT;
3443 goto out;
3444 }
3445 free(desc);
3446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003448stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003449 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 +01003450 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003453 }
3454 }
3455 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003456 int optnum;
3457
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003458 if (*(args[1]) == '\0') {
3459 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003463 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003464
3465 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3466 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003467 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3468 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3469 file, linenum, cfg_opts[optnum].name);
3470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
3472 }
Willy Tarreau93893792009-07-23 13:19:11 +02003473 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3474 err_code |= ERR_WARN;
3475 goto out;
3476 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003477
Willy Tarreau3842f002009-06-14 11:39:52 +02003478 curproxy->no_options &= ~cfg_opts[optnum].val;
3479 curproxy->options &= ~cfg_opts[optnum].val;
3480
3481 switch (kwm) {
3482 case KWM_STD:
3483 curproxy->options |= cfg_opts[optnum].val;
3484 break;
3485 case KWM_NO:
3486 curproxy->no_options |= cfg_opts[optnum].val;
3487 break;
3488 case KWM_DEF: /* already cleared */
3489 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003490 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003491
Willy Tarreau93893792009-07-23 13:19:11 +02003492 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003493 }
3494 }
3495
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003496 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3497 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003498 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3499 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3500 file, linenum, cfg_opts2[optnum].name);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
3503 }
Willy Tarreau93893792009-07-23 13:19:11 +02003504 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3505 err_code |= ERR_WARN;
3506 goto out;
3507 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003508
Willy Tarreau3842f002009-06-14 11:39:52 +02003509 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3510 curproxy->options2 &= ~cfg_opts2[optnum].val;
3511
3512 switch (kwm) {
3513 case KWM_STD:
3514 curproxy->options2 |= cfg_opts2[optnum].val;
3515 break;
3516 case KWM_NO:
3517 curproxy->no_options2 |= cfg_opts2[optnum].val;
3518 break;
3519 case KWM_DEF: /* already cleared */
3520 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003521 }
Willy Tarreau93893792009-07-23 13:19:11 +02003522 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003523 }
3524 }
3525
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003526 /* HTTP options override each other. They can be cancelled using
3527 * "no option xxx" which only switches to default mode if the mode
3528 * was this one (useful for cancelling options set in defaults
3529 * sections).
3530 */
3531 if (strcmp(args[1], "httpclose") == 0) {
3532 if (kwm == KWM_STD) {
3533 curproxy->options &= ~PR_O_HTTP_MODE;
3534 curproxy->options |= PR_O_HTTP_PCL;
3535 goto out;
3536 }
3537 else if (kwm == KWM_NO) {
3538 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3539 curproxy->options &= ~PR_O_HTTP_MODE;
3540 goto out;
3541 }
3542 }
3543 else if (strcmp(args[1], "forceclose") == 0) {
3544 if (kwm == KWM_STD) {
3545 curproxy->options &= ~PR_O_HTTP_MODE;
3546 curproxy->options |= PR_O_HTTP_FCL;
3547 goto out;
3548 }
3549 else if (kwm == KWM_NO) {
3550 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3551 curproxy->options &= ~PR_O_HTTP_MODE;
3552 goto out;
3553 }
3554 }
3555 else if (strcmp(args[1], "http-server-close") == 0) {
3556 if (kwm == KWM_STD) {
3557 curproxy->options &= ~PR_O_HTTP_MODE;
3558 curproxy->options |= PR_O_HTTP_SCL;
3559 goto out;
3560 }
3561 else if (kwm == KWM_NO) {
3562 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3563 curproxy->options &= ~PR_O_HTTP_MODE;
3564 goto out;
3565 }
3566 }
3567 else if (strcmp(args[1], "http-keep-alive") == 0) {
3568 if (kwm == KWM_STD) {
3569 curproxy->options &= ~PR_O_HTTP_MODE;
3570 curproxy->options |= PR_O_HTTP_KAL;
3571 goto out;
3572 }
3573 else if (kwm == KWM_NO) {
3574 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3575 curproxy->options &= ~PR_O_HTTP_MODE;
3576 goto out;
3577 }
3578 }
3579 else if (strcmp(args[1], "http-tunnel") == 0) {
3580 if (kwm == KWM_STD) {
3581 curproxy->options &= ~PR_O_HTTP_MODE;
3582 curproxy->options |= PR_O_HTTP_TUN;
3583 goto out;
3584 }
3585 else if (kwm == KWM_NO) {
3586 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3587 curproxy->options &= ~PR_O_HTTP_MODE;
3588 goto out;
3589 }
3590 }
3591
Willy Tarreau3842f002009-06-14 11:39:52 +02003592 if (kwm != KWM_STD) {
3593 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003594 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003597 }
3598
Emeric Brun3a058f32009-06-30 18:26:00 +02003599 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003600 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003602 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003603 if (*(args[2]) != '\0') {
3604 if (!strcmp(args[2], "clf")) {
3605 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003606 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003607 } else {
3608 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_ALERT | ERR_FATAL;
3610 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003611 }
3612 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003613 if (curproxy->conf.logformat_string != default_http_log_format &&
3614 curproxy->conf.logformat_string != default_tcp_log_format &&
3615 curproxy->conf.logformat_string != clf_http_log_format)
3616 free(curproxy->conf.logformat_string);
3617 curproxy->conf.logformat_string = logformat;
3618
3619 free(curproxy->conf.lfs_file);
3620 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3621 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003622 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003623 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003625 if (curproxy->conf.logformat_string != default_http_log_format &&
3626 curproxy->conf.logformat_string != default_tcp_log_format &&
3627 curproxy->conf.logformat_string != clf_http_log_format)
3628 free(curproxy->conf.logformat_string);
3629 curproxy->conf.logformat_string = default_tcp_log_format;
3630
3631 free(curproxy->conf.lfs_file);
3632 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3633 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 else if (!strcmp(args[1], "tcpka")) {
3636 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003637 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003639
3640 if (curproxy->cap & PR_CAP_FE)
3641 curproxy->options |= PR_O_TCP_CLI_KA;
3642 if (curproxy->cap & PR_CAP_BE)
3643 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
3645 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003646 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_WARN;
3648
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003650 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003651 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003652 curproxy->options2 &= ~PR_O2_CHK_ANY;
3653 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 if (!*args[2]) { /* no argument */
3655 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3656 curproxy->check_len = strlen(DEF_CHECK_REQ);
3657 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003658 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 curproxy->check_req = (char *)malloc(reqlen);
3660 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003661 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003663 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 if (*args[4])
3665 reqlen += strlen(args[4]);
3666 else
3667 reqlen += strlen("HTTP/1.0");
3668
3669 curproxy->check_req = (char *)malloc(reqlen);
3670 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003671 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003673 }
3674 else if (!strcmp(args[1], "ssl-hello-chk")) {
3675 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003676 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003677 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003678
Willy Tarreaua534fea2008-08-03 12:19:50 +02003679 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003680 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003681 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003682 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 }
Willy Tarreau23677902007-05-08 23:50:35 +02003684 else if (!strcmp(args[1], "smtpchk")) {
3685 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003686 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003687 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003688 curproxy->options2 &= ~PR_O2_CHK_ANY;
3689 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003690
3691 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3692 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3693 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3694 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3695 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3696 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3697 curproxy->check_req = (char *)malloc(reqlen);
3698 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3699 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3700 } else {
3701 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3702 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3703 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3704 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3705 }
3706 }
3707 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003708 else if (!strcmp(args[1], "pgsql-check")) {
3709 /* use PostgreSQL request to check servers' health */
3710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3711 err_code |= ERR_WARN;
3712
3713 free(curproxy->check_req);
3714 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003715 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003716 curproxy->options2 |= PR_O2_PGSQL_CHK;
3717
3718 if (*(args[2])) {
3719 int cur_arg = 2;
3720
3721 while (*(args[cur_arg])) {
3722 if (strcmp(args[cur_arg], "user") == 0) {
3723 char * packet;
3724 uint32_t packet_len;
3725 uint32_t pv;
3726
3727 /* suboption header - needs additional argument for it */
3728 if (*(args[cur_arg+1]) == 0) {
3729 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3730 file, linenum, args[0], args[1], args[cur_arg]);
3731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
3733 }
3734
3735 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3736 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3737 pv = htonl(0x30000); /* protocol version 3.0 */
3738
3739 packet = (char*) calloc(1, packet_len);
3740
3741 memcpy(packet + 4, &pv, 4);
3742
3743 /* copy "user" */
3744 memcpy(packet + 8, "user", 4);
3745
3746 /* copy username */
3747 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3748
3749 free(curproxy->check_req);
3750 curproxy->check_req = packet;
3751 curproxy->check_len = packet_len;
3752
3753 packet_len = htonl(packet_len);
3754 memcpy(packet, &packet_len, 4);
3755 cur_arg += 2;
3756 } else {
3757 /* unknown suboption - catchall */
3758 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3759 file, linenum, args[0], args[1]);
3760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
3762 }
3763 } /* end while loop */
3764 }
3765 }
3766
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003767 else if (!strcmp(args[1], "redis-check")) {
3768 /* use REDIS PING request to check servers' health */
3769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3770 err_code |= ERR_WARN;
3771
3772 free(curproxy->check_req);
3773 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003774 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003775 curproxy->options2 |= PR_O2_REDIS_CHK;
3776
3777 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3778 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3779 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3780 }
3781
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003782 else if (!strcmp(args[1], "mysql-check")) {
3783 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3785 err_code |= ERR_WARN;
3786
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003787 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003788 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003789 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003790 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003791
3792 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3793 * const char mysql40_client_auth_pkt[] = {
3794 * "\x0e\x00\x00" // packet length
3795 * "\x01" // packet number
3796 * "\x00\x00" // client capabilities
3797 * "\x00\x00\x01" // max packet
3798 * "haproxy\x00" // username (null terminated string)
3799 * "\x00" // filler (always 0x00)
3800 * "\x01\x00\x00" // packet length
3801 * "\x00" // packet number
3802 * "\x01" // COM_QUIT command
3803 * };
3804 */
3805
3806 if (*(args[2])) {
3807 int cur_arg = 2;
3808
3809 while (*(args[cur_arg])) {
3810 if (strcmp(args[cur_arg], "user") == 0) {
3811 char *mysqluser;
3812 int packetlen, reqlen, userlen;
3813
3814 /* suboption header - needs additional argument for it */
3815 if (*(args[cur_arg+1]) == 0) {
3816 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3817 file, linenum, args[0], args[1], args[cur_arg]);
3818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
3820 }
3821 mysqluser = args[cur_arg + 1];
3822 userlen = strlen(mysqluser);
3823 packetlen = userlen + 7;
3824 reqlen = packetlen + 9;
3825
3826 free(curproxy->check_req);
3827 curproxy->check_req = (char *)calloc(1, reqlen);
3828 curproxy->check_len = reqlen;
3829
3830 snprintf(curproxy->check_req, 4, "%c%c%c",
3831 ((unsigned char) packetlen & 0xff),
3832 ((unsigned char) (packetlen >> 8) & 0xff),
3833 ((unsigned char) (packetlen >> 16) & 0xff));
3834
3835 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003836 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003837 curproxy->check_req[8] = 1;
3838 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3839 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3840 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3841 cur_arg += 2;
3842 } else {
3843 /* unknown suboption - catchall */
3844 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3845 file, linenum, args[0], args[1]);
3846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
3849 } /* end while loop */
3850 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003851 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003852 else if (!strcmp(args[1], "ldap-check")) {
3853 /* use LDAP request to check servers' health */
3854 free(curproxy->check_req);
3855 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003856 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003857 curproxy->options2 |= PR_O2_LDAP_CHK;
3858
3859 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3860 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3861 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3862 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003863 else if (!strcmp(args[1], "tcp-check")) {
3864 /* use raw TCPCHK send/expect to check servers' health */
3865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3866 err_code |= ERR_WARN;
3867
3868 free(curproxy->check_req);
3869 curproxy->check_req = NULL;
3870 curproxy->options2 &= ~PR_O2_CHK_ANY;
3871 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3872 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003873 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003874 int cur_arg;
3875
3876 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3877 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003878 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003879
Willy Tarreau87cf5142011-08-19 22:57:24 +02003880 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003881
3882 free(curproxy->fwdfor_hdr_name);
3883 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3884 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3885
3886 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3887 cur_arg = 2;
3888 while (*(args[cur_arg])) {
3889 if (!strcmp(args[cur_arg], "except")) {
3890 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003891 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003892 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3893 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003896 }
3897 /* flush useless bits */
3898 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003899 cur_arg += 2;
3900 } else if (!strcmp(args[cur_arg], "header")) {
3901 /* suboption header - needs additional argument for it */
3902 if (*(args[cur_arg+1]) == 0) {
3903 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3904 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003907 }
3908 free(curproxy->fwdfor_hdr_name);
3909 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3910 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3911 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003912 } else if (!strcmp(args[cur_arg], "if-none")) {
3913 curproxy->options &= ~PR_O_FF_ALWAYS;
3914 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003915 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003916 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003917 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003918 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003921 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003922 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003923 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003924 else if (!strcmp(args[1], "originalto")) {
3925 int cur_arg;
3926
3927 /* insert x-original-to field, but not for the IP address listed as an except.
3928 * set default options (ie: bitfield, header name, etc)
3929 */
3930
3931 curproxy->options |= PR_O_ORGTO;
3932
3933 free(curproxy->orgto_hdr_name);
3934 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3935 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3936
Willy Tarreau87cf5142011-08-19 22:57:24 +02003937 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003938 cur_arg = 2;
3939 while (*(args[cur_arg])) {
3940 if (!strcmp(args[cur_arg], "except")) {
3941 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003942 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 +02003943 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3944 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003947 }
3948 /* flush useless bits */
3949 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3950 cur_arg += 2;
3951 } else if (!strcmp(args[cur_arg], "header")) {
3952 /* suboption header - needs additional argument for it */
3953 if (*(args[cur_arg+1]) == 0) {
3954 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3955 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003958 }
3959 free(curproxy->orgto_hdr_name);
3960 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3961 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3962 cur_arg += 2;
3963 } else {
3964 /* unknown suboption - catchall */
3965 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3966 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003969 }
3970 } /* end while loop */
3971 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 else {
3973 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 }
Willy Tarreau93893792009-07-23 13:19:11 +02003977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003979 else if (!strcmp(args[0], "default_backend")) {
3980 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003982
3983 if (*(args[1]) == 0) {
3984 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003987 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003988 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003989 curproxy->defbe.name = strdup(args[1]);
3990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003992 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003994
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003995 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3996 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998 /* enable reconnections to dispatch */
3999 curproxy->options |= PR_O_REDISP;
4000 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004001 else if (!strcmp(args[0], "http-check")) {
4002 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004004
4005 if (strcmp(args[1], "disable-on-404") == 0) {
4006 /* enable a graceful server shutdown on an HTTP 404 response */
4007 curproxy->options |= PR_O_DISABLE404;
4008 }
Willy Tarreauef781042010-01-27 11:53:01 +01004009 else if (strcmp(args[1], "send-state") == 0) {
4010 /* enable emission of the apparent state of a server in HTTP checks */
4011 curproxy->options2 |= PR_O2_CHK_SNDST;
4012 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004013 else if (strcmp(args[1], "expect") == 0) {
4014 const char *ptr_arg;
4015 int cur_arg;
4016
4017 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4018 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022
4023 cur_arg = 2;
4024 /* consider exclamation marks, sole or at the beginning of a word */
4025 while (*(ptr_arg = args[cur_arg])) {
4026 while (*ptr_arg == '!') {
4027 curproxy->options2 ^= PR_O2_EXP_INV;
4028 ptr_arg++;
4029 }
4030 if (*ptr_arg)
4031 break;
4032 cur_arg++;
4033 }
4034 /* now ptr_arg points to the beginning of a word past any possible
4035 * exclamation mark, and cur_arg is the argument which holds this word.
4036 */
4037 if (strcmp(ptr_arg, "status") == 0) {
4038 if (!*(args[cur_arg + 1])) {
4039 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4040 file, linenum, args[0], args[1], ptr_arg);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004045 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004046 curproxy->expect_str = strdup(args[cur_arg + 1]);
4047 }
4048 else if (strcmp(ptr_arg, "string") == 0) {
4049 if (!*(args[cur_arg + 1])) {
4050 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4051 file, linenum, args[0], args[1], ptr_arg);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004056 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004057 curproxy->expect_str = strdup(args[cur_arg + 1]);
4058 }
4059 else if (strcmp(ptr_arg, "rstatus") == 0) {
4060 if (!*(args[cur_arg + 1])) {
4061 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4062 file, linenum, args[0], args[1], ptr_arg);
4063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
4065 }
4066 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004067 free(curproxy->expect_str);
4068 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4069 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004070 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4071 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4072 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4073 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077 }
4078 else if (strcmp(ptr_arg, "rstring") == 0) {
4079 if (!*(args[cur_arg + 1])) {
4080 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4081 file, linenum, args[0], args[1], ptr_arg);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004086 free(curproxy->expect_str);
4087 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4088 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004089 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4090 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4091 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4092 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096 }
4097 else {
4098 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4099 file, linenum, args[0], args[1], ptr_arg);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004104 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004105 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 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004108 }
4109 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004110 else if (!strcmp(args[0], "tcp-check")) {
4111 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4112 err_code |= ERR_WARN;
4113
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004114 if (strcmp(args[1], "connect") == 0) {
4115 const char *ptr_arg;
4116 int cur_arg;
4117 struct tcpcheck_rule *tcpcheck;
4118 struct list *l;
4119
4120 /* check if first rule is also a 'connect' action */
4121 l = (struct list *)&curproxy->tcpcheck_rules;
4122 if (l->p != l->n) {
4123 tcpcheck = (struct tcpcheck_rule *)l->n;
4124 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4125 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4126 file, linenum);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
4129 }
4130 }
4131
4132 cur_arg = 2;
4133 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4134 tcpcheck->action = TCPCHK_ACT_CONNECT;
4135
4136 /* parsing each parameters to fill up the rule */
4137 while (*(ptr_arg = args[cur_arg])) {
4138 /* tcp port */
4139 if (strcmp(args[cur_arg], "port") == 0) {
4140 if ( (atol(args[cur_arg + 1]) > 65535) ||
4141 (atol(args[cur_arg + 1]) < 1) ){
4142 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4143 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147 tcpcheck->port = atol(args[cur_arg + 1]);
4148 cur_arg += 2;
4149 }
4150 /* send proxy protocol */
4151 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4152 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4153 cur_arg++;
4154 }
4155#ifdef USE_OPENSSL
4156 else if (strcmp(args[cur_arg], "ssl") == 0) {
4157 curproxy->options |= PR_O_TCPCHK_SSL;
4158 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4159 cur_arg++;
4160 }
4161#endif /* USE_OPENSSL */
4162 else {
4163#ifdef USE_OPENSSL
4164 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4165#else /* USE_OPENSSL */
4166 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4167#endif /* USE_OPENSSL */
4168 file, linenum, args[0], args[1], args[cur_arg]);
4169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
4171 }
4172
4173 }
4174
4175 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4176 }
4177 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004178 if (! *(args[2]) ) {
4179 /* SEND string expected */
4180 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4181 file, linenum, args[0], args[1], args[2]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 } else {
4185 struct tcpcheck_rule *tcpcheck;
4186
4187 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4188
4189 tcpcheck->action = TCPCHK_ACT_SEND;
4190 tcpcheck->string_len = strlen(args[2]);
4191 tcpcheck->string = strdup(args[2]);
4192 tcpcheck->expect_regex = NULL;
4193
4194 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4195 }
4196 }
4197 else if (strcmp(args[1], "send-binary") == 0) {
4198 if (! *(args[2]) ) {
4199 /* SEND binary string expected */
4200 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4201 file, linenum, args[0], args[1], args[2]);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 } else {
4205 struct tcpcheck_rule *tcpcheck;
4206 char *err = NULL;
4207
4208 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4209
4210 tcpcheck->action = TCPCHK_ACT_SEND;
4211 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4212 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4213 file, linenum, args[0], args[1], args[2], err);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216 }
4217 tcpcheck->expect_regex = NULL;
4218
4219 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4220 }
4221 }
4222 else if (strcmp(args[1], "expect") == 0) {
4223 const char *ptr_arg;
4224 int cur_arg;
4225 int inverse = 0;
4226
4227 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4228 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
4231 }
4232
4233 cur_arg = 2;
4234 /* consider exclamation marks, sole or at the beginning of a word */
4235 while (*(ptr_arg = args[cur_arg])) {
4236 while (*ptr_arg == '!') {
4237 inverse = !inverse;
4238 ptr_arg++;
4239 }
4240 if (*ptr_arg)
4241 break;
4242 cur_arg++;
4243 }
4244 /* now ptr_arg points to the beginning of a word past any possible
4245 * exclamation mark, and cur_arg is the argument which holds this word.
4246 */
4247 if (strcmp(ptr_arg, "binary") == 0) {
4248 if (!*(args[cur_arg + 1])) {
4249 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4250 file, linenum, args[0], args[1], ptr_arg);
4251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
4254 struct tcpcheck_rule *tcpcheck;
4255 char *err = NULL;
4256
4257 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4258
4259 tcpcheck->action = TCPCHK_ACT_EXPECT;
4260 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4261 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4262 file, linenum, args[0], args[1], args[2], err);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
4266 tcpcheck->expect_regex = NULL;
4267 tcpcheck->inverse = inverse;
4268
4269 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4270 }
4271 else if (strcmp(ptr_arg, "string") == 0) {
4272 if (!*(args[cur_arg + 1])) {
4273 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4274 file, linenum, args[0], args[1], ptr_arg);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
4278 struct tcpcheck_rule *tcpcheck;
4279
4280 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4281
4282 tcpcheck->action = TCPCHK_ACT_EXPECT;
4283 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4284 tcpcheck->string = strdup(args[cur_arg + 1]);
4285 tcpcheck->expect_regex = NULL;
4286 tcpcheck->inverse = inverse;
4287
4288 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4289 }
4290 else if (strcmp(ptr_arg, "rstring") == 0) {
4291 if (!*(args[cur_arg + 1])) {
4292 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4293 file, linenum, args[0], args[1], ptr_arg);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297 struct tcpcheck_rule *tcpcheck;
4298
4299 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4300
4301 tcpcheck->action = TCPCHK_ACT_EXPECT;
4302 tcpcheck->string_len = 0;
4303 tcpcheck->string = NULL;
4304 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4305 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4306 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4307 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 tcpcheck->inverse = inverse;
4312
4313 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4314 }
4315 else {
4316 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4317 file, linenum, args[0], args[1], ptr_arg);
4318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321 }
4322 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004323 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
4326 }
4327 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004328 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004329 if (curproxy == &defproxy) {
4330 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004333 }
4334
Willy Tarreaub80c2302007-11-30 20:51:32 +01004335 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004337
4338 if (strcmp(args[1], "fail") == 0) {
4339 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004340 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004341 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4342 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004345 }
4346
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004347 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4348 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4349 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004352 }
4353 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4354 }
4355 else {
4356 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004359 }
4360 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361#ifdef TPROXY
4362 else if (!strcmp(args[0], "transparent")) {
4363 /* enable transparent proxy connections */
4364 curproxy->options |= PR_O_TRANSP;
4365 }
4366#endif
4367 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004368 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004370
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 if (*(args[1]) == 0) {
4372 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375 }
4376 curproxy->maxconn = atol(args[1]);
4377 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004378 else if (!strcmp(args[0], "backlog")) { /* backlog */
4379 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004380 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004381
4382 if (*(args[1]) == 0) {
4383 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004386 }
4387 curproxy->backlog = atol(args[1]);
4388 }
Willy Tarreau86034312006-12-29 00:10:33 +01004389 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004392
Willy Tarreau86034312006-12-29 00:10:33 +01004393 if (*(args[1]) == 0) {
4394 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004397 }
4398 curproxy->fullconn = atol(args[1]);
4399 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4401 if (*(args[1]) == 0) {
4402 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004406 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4407 if (err) {
4408 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4409 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004412 }
4413 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 }
4415 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004416 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004417 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004418 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004419
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 if (curproxy == &defproxy) {
4421 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004424 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004425 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004426 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004427
Willy Tarreau902636f2013-03-10 19:44:48 +01004428 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004429 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004430 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004431 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004432 goto out;
4433 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004434
4435 proto = protocol_by_family(sk->ss_family);
4436 if (!proto || !proto->connect) {
4437 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4438 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
4442
4443 if (port1 != port2) {
4444 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4445 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004449
4450 if (!port1) {
4451 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4452 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004456
Willy Tarreaud5191e72010-02-09 20:50:45 +01004457 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004458 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 }
4460 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004461 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004463
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004464 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4465 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004469 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004470 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004471 /**
4472 * The syntax for hash-type config element is
4473 * hash-type {map-based|consistent} [[<algo>] avalanche]
4474 *
4475 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4476 */
4477 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004478
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004479 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4480 err_code |= ERR_WARN;
4481
4482 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004483 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4484 }
4485 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004486 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4487 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004488 else if (strcmp(args[1], "avalanche") == 0) {
4489 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]);
4490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004492 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004493 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004494 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
4497 }
Bhaskar98634f02013-10-29 23:30:51 -04004498
4499 /* set the hash function to use */
4500 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004501 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004502 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004503
4504 /* if consistent with no argument, then avalanche modifier is also applied */
4505 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4506 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004507 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004508 /* set the hash function */
4509 if (!strcmp(args[2], "sdbm")) {
4510 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4511 }
4512 else if (!strcmp(args[2], "djb2")) {
4513 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004514 } else if (!strcmp(args[2], "wt6")) {
4515 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004516 }
4517 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004518 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 -05004519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
4521 }
4522
4523 /* set the hash modifier */
4524 if (!strcmp(args[3], "avalanche")) {
4525 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4526 }
4527 else if (*args[3]) {
4528 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004532 }
William Lallemanda73203e2012-03-12 12:48:57 +01004533 }
William Lallemanda73203e2012-03-12 12:48:57 +01004534 else if (strcmp(args[0], "unique-id-format") == 0) {
4535 if (!*(args[1])) {
4536 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
William Lallemand3203ff42012-11-11 17:30:56 +01004540 if (*(args[2])) {
4541 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004545 free(curproxy->conf.uniqueid_format_string);
4546 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004547
Willy Tarreau62a61232013-04-12 18:13:46 +02004548 free(curproxy->conf.uif_file);
4549 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4550 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004551 }
William Lallemanda73203e2012-03-12 12:48:57 +01004552
4553 else if (strcmp(args[0], "unique-id-header") == 0) {
4554 if (!*(args[1])) {
4555 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
4558 }
4559 free(curproxy->header_unique_id);
4560 curproxy->header_unique_id = strdup(args[1]);
4561 }
4562
William Lallemand723b73a2012-02-08 16:37:49 +01004563 else if (strcmp(args[0], "log-format") == 0) {
4564 if (!*(args[1])) {
4565 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
William Lallemand3203ff42012-11-11 17:30:56 +01004569 if (*(args[2])) {
4570 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
4573 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004574
Willy Tarreau62a61232013-04-12 18:13:46 +02004575 if (curproxy->conf.logformat_string != default_http_log_format &&
4576 curproxy->conf.logformat_string != default_tcp_log_format &&
4577 curproxy->conf.logformat_string != clf_http_log_format)
4578 free(curproxy->conf.logformat_string);
4579 curproxy->conf.logformat_string = strdup(args[1]);
4580
4581 free(curproxy->conf.lfs_file);
4582 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4583 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004584
4585 /* get a chance to improve log-format error reporting by
4586 * reporting the correct line-number when possible.
4587 */
4588 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4589 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4590 file, linenum, curproxy->id);
4591 err_code |= ERR_WARN;
4592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004593 }
William Lallemand723b73a2012-02-08 16:37:49 +01004594
William Lallemand0f99e342011-10-12 17:50:54 +02004595 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4596 /* delete previous herited or defined syslog servers */
4597 struct logsrv *back;
4598
4599 if (*(args[1]) != 0) {
4600 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
4603 }
4604
William Lallemand723b73a2012-02-08 16:37:49 +01004605 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4606 LIST_DEL(&tmplogsrv->list);
4607 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004608 }
4609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004611 struct logsrv *logsrv;
4612
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004614 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004615 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004616 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004617 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004618 LIST_INIT(&node->list);
4619 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621 }
4622 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004623 struct sockaddr_storage *sk;
4624 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004625
4626 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627
William Lallemand0f99e342011-10-12 17:50:54 +02004628 logsrv->facility = get_log_facility(args[2]);
4629 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
4633
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 }
4635
William Lallemand0f99e342011-10-12 17:50:54 +02004636 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004638 logsrv->level = get_log_level(args[3]);
4639 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643
Willy Tarreaubaaee002006-06-26 02:48:02 +02004644 }
4645 }
4646
William Lallemand0f99e342011-10-12 17:50:54 +02004647 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004648 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004649 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004650 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004651 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
4654
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004655 }
4656 }
4657
Willy Tarreau902636f2013-03-10 19:44:48 +01004658 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004659 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004660 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004662 goto out;
4663 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004664
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004665 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004666
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004667 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004668 if (port1 != port2) {
4669 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4670 file, linenum, args[0], args[1]);
4671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
4673 }
4674
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004675 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004676 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 }
William Lallemand0f99e342011-10-12 17:50:54 +02004678
4679 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 }
4681 else {
4682 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4683 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004684 err_code |= ERR_ALERT | ERR_FATAL;
4685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 }
4687 }
4688 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004689 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004690 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004691 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004692 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004693
Willy Tarreau977b8e42006-12-29 14:19:17 +01004694 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004695 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004696
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004698 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4699 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004703
4704 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004705 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4706 free(curproxy->conn_src.iface_name);
4707 curproxy->conn_src.iface_name = NULL;
4708 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004709
Willy Tarreau902636f2013-03-10 19:44:48 +01004710 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004711 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004712 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004713 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004714 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004715 goto out;
4716 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004717
4718 proto = protocol_by_family(sk->ss_family);
4719 if (!proto || !proto->connect) {
4720 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004721 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004725
4726 if (port1 != port2) {
4727 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4728 file, linenum, args[0], args[1]);
4729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731 }
4732
Willy Tarreauef9a3602012-12-08 22:29:20 +01004733 curproxy->conn_src.source_addr = *sk;
4734 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004735
4736 cur_arg = 2;
4737 while (*(args[cur_arg])) {
4738 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004739#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4740#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004741 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004742 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4743 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004746 }
4747#endif
4748 if (!*args[cur_arg + 1]) {
4749 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4750 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004751 err_code |= ERR_ALERT | ERR_FATAL;
4752 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004753 }
4754
4755 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004756 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4757 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004758 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004759 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4760 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004761 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4762 char *name, *end;
4763
4764 name = args[cur_arg+1] + 7;
4765 while (isspace(*name))
4766 name++;
4767
4768 end = name;
4769 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4770 end++;
4771
Willy Tarreauef9a3602012-12-08 22:29:20 +01004772 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4773 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4774 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4775 curproxy->conn_src.bind_hdr_len = end - name;
4776 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4777 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4778 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004779
4780 /* now look for an occurrence number */
4781 while (isspace(*end))
4782 end++;
4783 if (*end == ',') {
4784 end++;
4785 name = end;
4786 if (*end == '-')
4787 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004788 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004789 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004790 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004791 }
4792
Willy Tarreauef9a3602012-12-08 22:29:20 +01004793 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004794 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4795 " occurrences values smaller than %d.\n",
4796 file, linenum, MAX_HDR_HISTORY);
4797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004800 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004801 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004802
Willy Tarreau902636f2013-03-10 19:44:48 +01004803 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004804 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004805 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004806 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004807 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004808 goto out;
4809 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004810
4811 proto = protocol_by_family(sk->ss_family);
4812 if (!proto || !proto->connect) {
4813 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4814 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004815 err_code |= ERR_ALERT | ERR_FATAL;
4816 goto out;
4817 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004818
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004819 if (port1 != port2) {
4820 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4821 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004825 curproxy->conn_src.tproxy_addr = *sk;
4826 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004827 }
4828 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004829#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004830 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004831#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004832#else /* no TPROXY support */
4833 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004834 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004837#endif
4838 cur_arg += 2;
4839 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004840 }
4841
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004842 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4843#ifdef SO_BINDTODEVICE
4844 if (!*args[cur_arg + 1]) {
4845 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4846 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004849 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004850 free(curproxy->conn_src.iface_name);
4851 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4852 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853 global.last_checks |= LSTCHK_NETADM;
4854#else
4855 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4856 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004859#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004860 cur_arg += 2;
4861 continue;
4862 }
4863 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004864 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004867 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004869 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4870 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4871 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004874 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004876 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4878 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004882
4883 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004884 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004885 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004886 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004888 }
4889 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004890 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004891 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004892 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004893 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895 }
4896 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004897 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004898 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004899 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004900 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 }
4903 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004905 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004906 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 }
4910 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004912 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004913 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004917 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004919 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004920 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004922 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004923 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004924 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004926 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004927 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004929 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004930 }
4931 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004933 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004934 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4941 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945
4946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004947 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004948 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004954 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004955 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
4959 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004961 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004962 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004968 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004975 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004976 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004980 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004982 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004983 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004985 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004988 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004989
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 if (curproxy == &defproxy) {
4991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004995 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 if (*(args[1]) == 0) {
4999 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005003
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005004 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005005 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5006 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5007 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005011 err_code |= warnif_cond_conflicts(cond,
5012 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5013 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005014 }
5015 else if (*args[2]) {
5016 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5017 file, linenum, args[0], args[2]);
5018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
5020 }
5021
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005022 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005023 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005024 wl->s = strdup(args[1]);
5025 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005026 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 }
5028 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005034 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005035
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005037 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005038 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 }
5042 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005044 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005045 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
5049 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005051 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005052 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
5056 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005057 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005058 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5059 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 }
5063
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005065 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005066 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005067 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 }
5070 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005072 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005073 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005074 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
5077 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005079 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005080 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005081 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
5084 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005085 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005086
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 if (curproxy == &defproxy) {
5088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005092 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005093 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 if (*(args[1]) == 0) {
5096 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005097 err_code |= ERR_ALERT | ERR_FATAL;
5098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 }
5100
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005101 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005102 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5103 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5104 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
5107 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005108 err_code |= warnif_cond_conflicts(cond,
5109 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5110 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005111 }
5112 else if (*args[2]) {
5113 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5114 file, linenum, args[0], args[2]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005119 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005120 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005121 wl->s = strdup(args[1]);
5122 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 }
5124 else if (!strcmp(args[0], "errorloc") ||
5125 !strcmp(args[0], "errorloc302") ||
5126 !strcmp(args[0], "errorloc303")) { /* error location */
5127 int errnum, errlen;
5128 char *err;
5129
Willy Tarreau977b8e42006-12-29 14:19:17 +01005130 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005132
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005134 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
5138
5139 errnum = atol(args[1]);
5140 if (!strcmp(args[0], "errorloc303")) {
5141 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5142 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5143 } else {
5144 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5145 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5146 }
5147
Willy Tarreau0f772532006-12-23 20:51:41 +01005148 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5149 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005150 chunk_destroy(&curproxy->errmsg[rc]);
5151 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005152 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005155
5156 if (rc >= HTTP_ERR_SIZE) {
5157 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5158 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 free(err);
5160 }
5161 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005162 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5163 int errnum, errlen, fd;
5164 char *err;
5165 struct stat stat;
5166
5167 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005168 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005169
5170 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005171 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005174 }
5175
5176 fd = open(args[2], O_RDONLY);
5177 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5178 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5179 file, linenum, args[2], args[1]);
5180 if (fd >= 0)
5181 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005184 }
5185
Willy Tarreau27a674e2009-08-17 07:23:33 +02005186 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005187 errlen = stat.st_size;
5188 } else {
5189 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005190 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005192 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005193 }
5194
5195 err = malloc(errlen); /* malloc() must succeed during parsing */
5196 errnum = read(fd, err, errlen);
5197 if (errnum != errlen) {
5198 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5199 file, linenum, args[2], args[1]);
5200 close(fd);
5201 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005204 }
5205 close(fd);
5206
5207 errnum = atol(args[1]);
5208 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5209 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005210 chunk_destroy(&curproxy->errmsg[rc]);
5211 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005212 break;
5213 }
5214 }
5215
5216 if (rc >= HTTP_ERR_SIZE) {
5217 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5218 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005220 free(err);
5221 }
5222 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005223 else if (!strcmp(args[0], "compression")) {
5224 struct comp *comp;
5225 if (curproxy->comp == NULL) {
5226 comp = calloc(1, sizeof(struct comp));
5227 curproxy->comp = comp;
5228 } else {
5229 comp = curproxy->comp;
5230 }
5231
5232 if (!strcmp(args[1], "algo")) {
5233 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005234 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005235
William Lallemand82fe75c2012-10-23 10:25:10 +02005236 cur_arg = 2;
5237 if (!*args[cur_arg]) {
5238 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5239 file, linenum, args[0]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243 while (*(args[cur_arg])) {
5244 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5245 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5246 file, linenum, args[0], args[cur_arg]);
5247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
William Lallemand552df672012-11-07 13:21:47 +01005250 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5251 curproxy->comp->algos->end(&ctx);
5252 } else {
5253 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5254 file, linenum, args[0], args[cur_arg]);
5255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
5257 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005258 cur_arg ++;
5259 continue;
5260 }
5261 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005262 else if (!strcmp(args[1], "offload")) {
5263 comp->offload = 1;
5264 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005265 else if (!strcmp(args[1], "type")) {
5266 int cur_arg;
5267 cur_arg = 2;
5268 if (!*args[cur_arg]) {
5269 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5270 file, linenum, args[0]);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274 while (*(args[cur_arg])) {
5275 comp_append_type(comp, args[cur_arg]);
5276 cur_arg ++;
5277 continue;
5278 }
5279 }
5280 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005281 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005282 file, linenum, args[0]);
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
5286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005288 struct cfg_kw_list *kwl;
5289 int index;
5290
5291 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5292 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5293 if (kwl->kw[index].section != CFG_LISTEN)
5294 continue;
5295 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5296 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005297 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005298 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005299 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005302 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005303 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005304 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005305 err_code |= ERR_WARN;
5306 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005307 }
Willy Tarreau93893792009-07-23 13:19:11 +02005308 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005309 }
5310 }
5311 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005312
Willy Tarreau6daf3432008-01-22 16:44:08 +01005313 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
Willy Tarreau93893792009-07-23 13:19:11 +02005317 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005318 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005319 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320}
5321
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005322int
5323cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5324{
5325
5326 int err_code = 0;
5327 const char *err;
5328
5329 if (!strcmp(args[0], "userlist")) { /* new userlist */
5330 struct userlist *newul;
5331
5332 if (!*args[1]) {
5333 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5334 file, linenum, args[0]);
5335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
5338
5339 err = invalid_char(args[1]);
5340 if (err) {
5341 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5342 file, linenum, *err, args[0], args[1]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346
5347 for (newul = userlist; newul; newul = newul->next)
5348 if (!strcmp(newul->name, args[1])) {
5349 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5350 file, linenum, args[1]);
5351 err_code |= ERR_WARN;
5352 goto out;
5353 }
5354
5355 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5356 if (!newul) {
5357 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5358 err_code |= ERR_ALERT | ERR_ABORT;
5359 goto out;
5360 }
5361
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005362 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005363 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005364 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5365 err_code |= ERR_ALERT | ERR_ABORT;
5366 goto out;
5367 }
5368
5369 newul->next = userlist;
5370 userlist = newul;
5371
5372 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005373 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005374 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005375 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005376
5377 if (!*args[1]) {
5378 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5379 file, linenum, args[0]);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383
5384 err = invalid_char(args[1]);
5385 if (err) {
5386 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5387 file, linenum, *err, args[0], args[1]);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
5391
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005392 for (ag = userlist->groups; ag; ag = ag->next)
5393 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005394 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5395 file, linenum, args[1], userlist->name);
5396 err_code |= ERR_ALERT;
5397 goto out;
5398 }
5399
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005400 ag = calloc(1, sizeof(*ag));
5401 if (!ag) {
5402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5403 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005404 goto out;
5405 }
5406
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005407 ag->name = strdup(args[1]);
5408 if (!ag) {
5409 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5410 err_code |= ERR_ALERT | ERR_ABORT;
5411 goto out;
5412 }
5413
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005414 cur_arg = 2;
5415
5416 while (*args[cur_arg]) {
5417 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005418 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005419 cur_arg += 2;
5420 continue;
5421 } else {
5422 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5423 file, linenum, args[0]);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
5427 }
5428
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005429 ag->next = userlist->groups;
5430 userlist->groups = ag;
5431
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005432 } else if (!strcmp(args[0], "user")) { /* new user */
5433 struct auth_users *newuser;
5434 int cur_arg;
5435
5436 if (!*args[1]) {
5437 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5438 file, linenum, args[0]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442
5443 for (newuser = userlist->users; newuser; newuser = newuser->next)
5444 if (!strcmp(newuser->user, args[1])) {
5445 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5446 file, linenum, args[1], userlist->name);
5447 err_code |= ERR_ALERT;
5448 goto out;
5449 }
5450
5451 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5452 if (!newuser) {
5453 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5454 err_code |= ERR_ALERT | ERR_ABORT;
5455 goto out;
5456 }
5457
5458 newuser->user = strdup(args[1]);
5459
5460 newuser->next = userlist->users;
5461 userlist->users = newuser;
5462
5463 cur_arg = 2;
5464
5465 while (*args[cur_arg]) {
5466 if (!strcmp(args[cur_arg], "password")) {
5467#ifndef CONFIG_HAP_CRYPT
5468 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5469 file, linenum);
5470 err_code |= ERR_ALERT;
5471#endif
5472 newuser->pass = strdup(args[cur_arg + 1]);
5473 cur_arg += 2;
5474 continue;
5475 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5476 newuser->pass = strdup(args[cur_arg + 1]);
5477 newuser->flags |= AU_O_INSECURE;
5478 cur_arg += 2;
5479 continue;
5480 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005481 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005482 cur_arg += 2;
5483 continue;
5484 } else {
5485 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5486 file, linenum, args[0]);
5487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
5489 }
5490 }
5491 } else {
5492 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5493 err_code |= ERR_ALERT | ERR_FATAL;
5494 }
5495
5496out:
5497 return err_code;
5498}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499
5500/*
5501 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005502 * Returns the error code, 0 if OK, or any combination of :
5503 * - ERR_ABORT: must abort ASAP
5504 * - ERR_FATAL: we can continue parsing but not start the service
5505 * - ERR_WARN: a warning has been emitted
5506 * - ERR_ALERT: an alert has been emitted
5507 * Only the two first ones can stop processing, the two others are just
5508 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005510int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005512 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005513 FILE *f;
5514 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005515 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005516 struct cfg_section *cs = NULL;
5517 struct cfg_section *ics;
5518
5519 /* Register internal sections */
5520 if (!cfg_register_section("listen", cfg_parse_listen) ||
5521 !cfg_register_section("frontend", cfg_parse_listen) ||
5522 !cfg_register_section("backend", cfg_parse_listen) ||
5523 !cfg_register_section("ruleset", cfg_parse_listen) ||
5524 !cfg_register_section("defaults", cfg_parse_listen) ||
5525 !cfg_register_section("global", cfg_parse_global) ||
5526 !cfg_register_section("userlist", cfg_parse_users) ||
5527 !cfg_register_section("peers", cfg_parse_peers))
5528 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 if ((f=fopen(file,"r")) == NULL)
5531 return -1;
5532
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005533 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005534 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005535 char *end;
5536 char *args[MAX_LINE_ARGS + 1];
5537 char *line = thisline;
5538
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 linenum++;
5540
5541 end = line + strlen(line);
5542
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005543 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5544 /* Check if we reached the limit and the last char is not \n.
5545 * Watch out for the last line without the terminating '\n'!
5546 */
5547 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005548 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005549 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005550 }
5551
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005553 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 line++;
5555
5556 arg = 0;
5557 args[arg] = line;
5558
5559 while (*line && arg < MAX_LINE_ARGS) {
5560 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5561 * C equivalent value. Other combinations left unchanged (eg: \1).
5562 */
5563 if (*line == '\\') {
5564 int skip = 0;
5565 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5566 *line = line[1];
5567 skip = 1;
5568 }
5569 else if (line[1] == 'r') {
5570 *line = '\r';
5571 skip = 1;
5572 }
5573 else if (line[1] == 'n') {
5574 *line = '\n';
5575 skip = 1;
5576 }
5577 else if (line[1] == 't') {
5578 *line = '\t';
5579 skip = 1;
5580 }
5581 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005582 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 unsigned char hex1, hex2;
5584 hex1 = toupper(line[2]) - '0';
5585 hex2 = toupper(line[3]) - '0';
5586 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5587 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5588 *line = (hex1<<4) + hex2;
5589 skip = 3;
5590 }
5591 else {
5592 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
5595 }
5596 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005597 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 end -= skip;
5599 }
5600 line++;
5601 }
5602 else if (*line == '#' || *line == '\n' || *line == '\r') {
5603 /* end of string, end of loop */
5604 *line = 0;
5605 break;
5606 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005607 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005609 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005610 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611 line++;
5612 args[++arg] = line;
5613 }
5614 else {
5615 line++;
5616 }
5617 }
5618
5619 /* empty line */
5620 if (!**args)
5621 continue;
5622
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005623 if (*line) {
5624 /* we had to stop due to too many args.
5625 * Let's terminate the string, print the offending part then cut the
5626 * last arg.
5627 */
5628 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5629 line++;
5630 *line = '\0';
5631
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005632 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005633 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005634 err_code |= ERR_ALERT | ERR_FATAL;
5635 args[arg] = line;
5636 }
5637
Willy Tarreau540abe42007-05-02 20:50:16 +02005638 /* zero out remaining args and ensure that at least one entry
5639 * is zeroed out.
5640 */
5641 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005642 args[arg] = line;
5643 }
5644
Willy Tarreau3842f002009-06-14 11:39:52 +02005645 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005646 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005647 char *tmp;
5648
Willy Tarreau3842f002009-06-14 11:39:52 +02005649 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005650 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005651 for (arg=0; *args[arg+1]; arg++)
5652 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005653 *tmp = '\0'; // fix the next arg to \0
5654 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005655 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005656 else if (!strcmp(args[0], "default")) {
5657 kwm = KWM_DEF;
5658 for (arg=0; *args[arg+1]; arg++)
5659 args[arg] = args[arg+1]; // shift args after inversion
5660 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005661
William Lallemand0f99e342011-10-12 17:50:54 +02005662 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5663 strcmp(args[0], "log") != 0) {
5664 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005665 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005666 }
5667
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005668 /* detect section start */
5669 list_for_each_entry(ics, &sections, list) {
5670 if (strcmp(args[0], ics->section_name) == 0) {
5671 cursection = ics->section_name;
5672 cs = ics;
5673 break;
5674 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005675 }
5676
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005678 if (cs)
5679 err_code |= cs->section_parser(file, linenum, args, kwm);
5680 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005681 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005684
5685 if (err_code & ERR_ABORT)
5686 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005688 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005690 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005691}
5692
Willy Tarreaubb925012009-07-23 13:36:36 +02005693/*
5694 * Returns the error code, 0 if OK, or any combination of :
5695 * - ERR_ABORT: must abort ASAP
5696 * - ERR_FATAL: we can continue parsing but not start the service
5697 * - ERR_WARN: a warning has been emitted
5698 * - ERR_ALERT: an alert has been emitted
5699 * Only the two first ones can stop processing, the two others are just
5700 * indicators.
5701 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005702int check_config_validity()
5703{
5704 int cfgerr = 0;
5705 struct proxy *curproxy = NULL;
5706 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005707 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005708 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005709 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005711 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 /*
5713 * Now, check for the integrity of all that we have collected.
5714 */
5715
5716 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005717 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718
Willy Tarreau193b8c62012-11-22 00:17:38 +01005719 if (!global.tune.max_http_hdr)
5720 global.tune.max_http_hdr = MAX_HTTP_HDR;
5721
5722 if (!global.tune.cookie_len)
5723 global.tune.cookie_len = CAPTURE_LEN;
5724
5725 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5726
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005727 /* Post initialisation of the users and groups lists. */
5728 err_code = userlist_postinit();
5729 if (err_code != ERR_NONE)
5730 goto out;
5731
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005732 /* first, we will invert the proxy list order */
5733 curproxy = NULL;
5734 while (proxy) {
5735 struct proxy *next;
5736
5737 next = proxy->next;
5738 proxy->next = curproxy;
5739 curproxy = proxy;
5740 if (!next)
5741 break;
5742 proxy = next;
5743 }
5744
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005746 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005747 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005748 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005749 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005750 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005751 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005752 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005753
Willy Tarreau050536d2012-10-04 08:47:34 +02005754 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005755 /* proxy ID not set, use automatic numbering with first
5756 * spare entry starting with next_pxid.
5757 */
5758 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5759 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5760 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005761 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005762 next_pxid++;
5763
Willy Tarreau55ea7572007-06-17 19:56:27 +02005764
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005766 /* ensure we don't keep listeners uselessly bound */
5767 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 curproxy = curproxy->next;
5769 continue;
5770 }
5771
Willy Tarreau16a21472012-11-19 12:39:59 +01005772 /* number of processes this proxy is bound to */
5773 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5774
Willy Tarreauff01a212009-03-15 13:46:16 +01005775 switch (curproxy->mode) {
5776 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005777 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005778 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005779 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5780 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005781 cfgerr++;
5782 }
5783
5784 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005785 Warning("config : servers will be ignored for %s '%s'.\n",
5786 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005787 break;
5788
5789 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005790 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005791 break;
5792
5793 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005794 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005795 break;
5796 }
5797
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005798 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005799 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005800 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005801 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5802 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005803 cfgerr++;
5804 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005806 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005807 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5808 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005809 cfgerr++;
5810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005812 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005813 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5814 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005815 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005816 }
5817 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005818 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005819 /* If no LB algo is set in a backend, and we're not in
5820 * transparent mode, dispatch mode nor proxy mode, we
5821 * want to use balance roundrobin by default.
5822 */
5823 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5824 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 }
5826 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005827
Willy Tarreau1620ec32011-08-06 17:05:02 +02005828 if (curproxy->options & PR_O_DISPATCH)
5829 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5830 else if (curproxy->options & PR_O_HTTP_PROXY)
5831 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5832 else if (curproxy->options & PR_O_TRANSP)
5833 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005834
Willy Tarreau1620ec32011-08-06 17:05:02 +02005835 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5836 if (curproxy->options & PR_O_DISABLE404) {
5837 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5838 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5839 err_code |= ERR_WARN;
5840 curproxy->options &= ~PR_O_DISABLE404;
5841 }
5842 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5843 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5844 "send-state", proxy_type_str(curproxy), curproxy->id);
5845 err_code |= ERR_WARN;
5846 curproxy->options &= ~PR_O2_CHK_SNDST;
5847 }
Willy Tarreauef781042010-01-27 11:53:01 +01005848 }
5849
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005850 /* if a default backend was specified, let's find it */
5851 if (curproxy->defbe.name) {
5852 struct proxy *target;
5853
Alex Williams96532db2009-11-01 21:27:13 -05005854 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005855 if (!target) {
5856 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5857 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005858 cfgerr++;
5859 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005860 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5861 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005862 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005863 } else {
5864 free(curproxy->defbe.name);
5865 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005866 /* we force the backend to be present on at least all of
5867 * the frontend's processes.
5868 */
5869 target->bind_proc = curproxy->bind_proc ?
5870 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005871
5872 /* Emit a warning if this proxy also has some servers */
5873 if (curproxy->srv) {
5874 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5875 curproxy->id);
5876 err_code |= ERR_WARN;
5877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
5879 }
5880
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005881 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005882 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5883 /* map jump target for ACT_SETBE in req_rep chain */
5884 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005885 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005886 struct proxy *target;
5887
Willy Tarreaua496b602006-12-17 23:15:24 +01005888 if (exp->action != ACT_SETBE)
5889 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005890
Alex Williams96532db2009-11-01 21:27:13 -05005891 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005892 if (!target) {
5893 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5894 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005895 cfgerr++;
5896 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005897 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5898 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005899 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005900 } else {
5901 free((void *)exp->replace);
5902 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005903 /* we force the backend to be present on at least all of
5904 * the frontend's processes.
5905 */
5906 target->bind_proc = curproxy->bind_proc ?
5907 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005908 }
5909 }
5910 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005911
5912 /* find the target proxy for 'use_backend' rules */
5913 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005914 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005915 struct logformat_node *node;
5916 char *pxname;
5917
5918 /* Try to parse the string as a log format expression. If the result
5919 * of the parsing is only one entry containing a simple string, then
5920 * it's a standard string corresponding to a static rule, thus the
5921 * parsing is cancelled and be.name is restored to be resolved.
5922 */
5923 pxname = rule->be.name;
5924 LIST_INIT(&rule->be.expr);
5925 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
5926 curproxy->conf.args.file, curproxy->conf.args.line);
5927 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
5928
5929 if (!LIST_ISEMPTY(&rule->be.expr)) {
5930 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
5931 rule->dynamic = 1;
5932 free(pxname);
5933 continue;
5934 }
5935 /* simple string: free the expression and fall back to static rule */
5936 free(node->arg);
5937 free(node);
5938 }
5939
5940 rule->dynamic = 0;
5941 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005942
Alex Williams96532db2009-11-01 21:27:13 -05005943 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005944
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005945 if (!target) {
5946 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5947 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005948 cfgerr++;
5949 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005950 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5951 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005952 cfgerr++;
5953 } else {
5954 free((void *)rule->be.name);
5955 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005956 /* we force the backend to be present on at least all of
5957 * the frontend's processes.
5958 */
5959 target->bind_proc = curproxy->bind_proc ?
5960 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005961 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005962 }
5963
5964 /* find the target proxy for 'use_backend' rules */
5965 list_for_each_entry(srule, &curproxy->server_rules, list) {
5966 struct server *target = findserver(curproxy, srule->srv.name);
5967
5968 if (!target) {
5969 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5970 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5971 cfgerr++;
5972 continue;
5973 }
5974 free((void *)srule->srv.name);
5975 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005976 }
5977
Emeric Brunb982a3d2010-01-04 15:45:53 +01005978 /* find the target table for 'stick' rules */
5979 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5980 struct proxy *target;
5981
Emeric Brun1d33b292010-01-04 15:47:17 +01005982 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5983 if (mrule->flags & STK_IS_STORE)
5984 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5985
Emeric Brunb982a3d2010-01-04 15:45:53 +01005986 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005987 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005988 else
5989 target = curproxy;
5990
5991 if (!target) {
5992 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5993 curproxy->id, mrule->table.name);
5994 cfgerr++;
5995 }
5996 else if (target->table.size == 0) {
5997 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5998 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5999 cfgerr++;
6000 }
Willy Tarreau12785782012-04-27 21:37:17 +02006001 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6002 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006003 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6004 cfgerr++;
6005 }
6006 else {
6007 free((void *)mrule->table.name);
6008 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006009 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006010 }
6011 }
6012
6013 /* find the target table for 'store response' rules */
6014 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6015 struct proxy *target;
6016
Emeric Brun1d33b292010-01-04 15:47:17 +01006017 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6018
Emeric Brunb982a3d2010-01-04 15:45:53 +01006019 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006020 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006021 else
6022 target = curproxy;
6023
6024 if (!target) {
6025 Alert("Proxy '%s': unable to find store table '%s'.\n",
6026 curproxy->id, mrule->table.name);
6027 cfgerr++;
6028 }
6029 else if (target->table.size == 0) {
6030 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6031 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6032 cfgerr++;
6033 }
Willy Tarreau12785782012-04-27 21:37:17 +02006034 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6035 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006036 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6037 cfgerr++;
6038 }
6039 else {
6040 free((void *)mrule->table.name);
6041 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006042 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006043 }
6044 }
6045
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006046 /* find the target table for 'tcp-request' layer 4 rules */
6047 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6048 struct proxy *target;
6049
Willy Tarreaub4c84932013-07-23 19:15:30 +02006050 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006051 continue;
6052
6053 if (trule->act_prm.trk_ctr.table.n)
6054 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6055 else
6056 target = curproxy;
6057
6058 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006059 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6060 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006061 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006062 cfgerr++;
6063 }
6064 else if (target->table.size == 0) {
6065 Alert("Proxy '%s': table '%s' used but not configured.\n",
6066 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6067 cfgerr++;
6068 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006069 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6070 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6071 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 +01006072 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006073 cfgerr++;
6074 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006075 else {
6076 free(trule->act_prm.trk_ctr.table.n);
6077 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006078 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006079 * to pass a list of counters to track and allocate them right here using
6080 * stktable_alloc_data_type().
6081 */
6082 }
6083 }
6084
Willy Tarreaud1f96522010-08-03 19:34:32 +02006085 /* find the target table for 'tcp-request' layer 6 rules */
6086 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6087 struct proxy *target;
6088
Willy Tarreaub4c84932013-07-23 19:15:30 +02006089 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006090 continue;
6091
6092 if (trule->act_prm.trk_ctr.table.n)
6093 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6094 else
6095 target = curproxy;
6096
6097 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006098 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6099 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006100 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006101 cfgerr++;
6102 }
6103 else if (target->table.size == 0) {
6104 Alert("Proxy '%s': table '%s' used but not configured.\n",
6105 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6106 cfgerr++;
6107 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006108 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6109 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6110 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 +01006111 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006112 cfgerr++;
6113 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006114 else {
6115 free(trule->act_prm.trk_ctr.table.n);
6116 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006117 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006118 * to pass a list of counters to track and allocate them right here using
6119 * stktable_alloc_data_type().
6120 */
6121 }
6122 }
6123
Emeric Brun32da3c42010-09-23 18:39:19 +02006124 if (curproxy->table.peers.name) {
6125 struct peers *curpeers = peers;
6126
6127 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6128 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6129 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006130 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006131 break;
6132 }
6133 }
6134
6135 if (!curpeers) {
6136 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6137 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006138 free((void *)curproxy->table.peers.name);
6139 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006140 cfgerr++;
6141 }
6142 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006143 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6144 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006145 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006146 cfgerr++;
6147 }
6148 }
6149
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006150 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006151 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006152 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6153 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6154 "proxy", curproxy->id);
6155 cfgerr++;
6156 goto out_uri_auth_compat;
6157 }
6158
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006159 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006160 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006161 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006162 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006163
Willy Tarreau95fa4692010-02-01 13:05:50 +01006164 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6165 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006166
6167 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006168 uri_auth_compat_req[i++] = "realm";
6169 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6170 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006171
Willy Tarreau95fa4692010-02-01 13:05:50 +01006172 uri_auth_compat_req[i++] = "unless";
6173 uri_auth_compat_req[i++] = "{";
6174 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6175 uri_auth_compat_req[i++] = "}";
6176 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006177
Willy Tarreauff011f22011-01-06 17:51:27 +01006178 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6179 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006180 cfgerr++;
6181 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006182 }
6183
Willy Tarreauff011f22011-01-06 17:51:27 +01006184 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006185
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006186 if (curproxy->uri_auth->auth_realm) {
6187 free(curproxy->uri_auth->auth_realm);
6188 curproxy->uri_auth->auth_realm = NULL;
6189 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006190
6191 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006192 }
6193out_uri_auth_compat:
6194
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006195 /* compile the log format */
6196 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006197 if (curproxy->conf.logformat_string != default_http_log_format &&
6198 curproxy->conf.logformat_string != default_tcp_log_format &&
6199 curproxy->conf.logformat_string != clf_http_log_format)
6200 free(curproxy->conf.logformat_string);
6201 curproxy->conf.logformat_string = NULL;
6202 free(curproxy->conf.lfs_file);
6203 curproxy->conf.lfs_file = NULL;
6204 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006205 }
6206
Willy Tarreau62a61232013-04-12 18:13:46 +02006207 if (curproxy->conf.logformat_string) {
6208 curproxy->conf.args.ctx = ARGC_LOG;
6209 curproxy->conf.args.file = curproxy->conf.lfs_file;
6210 curproxy->conf.args.line = curproxy->conf.lfs_line;
6211 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006212 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006213 curproxy->conf.args.file = NULL;
6214 curproxy->conf.args.line = 0;
6215 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006216
Willy Tarreau62a61232013-04-12 18:13:46 +02006217 if (curproxy->conf.uniqueid_format_string) {
6218 curproxy->conf.args.ctx = ARGC_UIF;
6219 curproxy->conf.args.file = curproxy->conf.uif_file;
6220 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006221 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006222 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6223 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006224 curproxy->conf.args.file = NULL;
6225 curproxy->conf.args.line = 0;
6226 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006227
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006228 /* only now we can check if some args remain unresolved.
6229 * This must be done after the users and groups resolution.
6230 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006231 cfgerr += smp_resolve_args(curproxy);
6232 if (!cfgerr)
6233 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006234
Willy Tarreau2738a142006-07-08 17:28:09 +02006235 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006236 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006237 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006238 (!curproxy->timeout.connect ||
6239 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006240 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006241 " | While not properly invalid, you will certainly encounter various problems\n"
6242 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006243 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006244 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006245 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006246 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006247
Willy Tarreau1fa31262007-12-03 00:36:16 +01006248 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6249 * We must still support older configurations, so let's find out whether those
6250 * parameters have been set or must be copied from contimeouts.
6251 */
6252 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006253 if (!curproxy->timeout.tarpit ||
6254 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006255 /* tarpit timeout not set. We search in the following order:
6256 * default.tarpit, curr.connect, default.connect.
6257 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006258 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006259 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006260 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006261 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006262 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006263 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006264 }
6265 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006266 (!curproxy->timeout.queue ||
6267 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006268 /* queue timeout not set. We search in the following order:
6269 * default.queue, curr.connect, default.connect.
6270 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006271 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006272 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006273 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006274 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006275 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006276 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006277 }
6278 }
6279
Willy Tarreau1620ec32011-08-06 17:05:02 +02006280 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006281 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6282 curproxy->check_req = (char *)malloc(curproxy->check_len);
6283 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006284 }
6285
Willy Tarreau193b8c62012-11-22 00:17:38 +01006286 /* ensure that cookie capture length is not too large */
6287 if (curproxy->capture_len >= global.tune.cookie_len) {
6288 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6289 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6290 err_code |= ERR_WARN;
6291 curproxy->capture_len = global.tune.cookie_len - 1;
6292 }
6293
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006294 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006295 if (curproxy->nb_req_cap) {
6296 if (curproxy->mode == PR_MODE_HTTP) {
6297 curproxy->req_cap_pool = create_pool("ptrcap",
6298 curproxy->nb_req_cap * sizeof(char *),
6299 MEM_F_SHARED);
6300 } else {
6301 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6302 proxy_type_str(curproxy), curproxy->id);
6303 err_code |= ERR_WARN;
6304 curproxy->to_log &= ~LW_REQHDR;
6305 curproxy->nb_req_cap = 0;
6306 }
6307 }
6308
6309 if (curproxy->nb_rsp_cap) {
6310 if (curproxy->mode == PR_MODE_HTTP) {
6311 curproxy->rsp_cap_pool = create_pool("ptrcap",
6312 curproxy->nb_rsp_cap * sizeof(char *),
6313 MEM_F_SHARED);
6314 } else {
6315 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6316 proxy_type_str(curproxy), curproxy->id);
6317 err_code |= ERR_WARN;
6318 curproxy->to_log &= ~LW_REQHDR;
6319 curproxy->nb_rsp_cap = 0;
6320 }
6321 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006322
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 /* first, we will invert the servers list order */
6324 newsrv = NULL;
6325 while (curproxy->srv) {
6326 struct server *next;
6327
6328 next = curproxy->srv->next;
6329 curproxy->srv->next = newsrv;
6330 newsrv = curproxy->srv;
6331 if (!next)
6332 break;
6333 curproxy->srv = next;
6334 }
6335
Willy Tarreau17edc812014-01-03 12:14:34 +01006336 /* Check that no server name conflicts. This causes trouble in the stats.
6337 * We only emit a warning for the first conflict affecting each server,
6338 * in order to avoid combinatory explosion if all servers have the same
6339 * name. We do that only for servers which do not have an explicit ID,
6340 * because these IDs were made also for distinguishing them and we don't
6341 * want to annoy people who correctly manage them.
6342 */
6343 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6344 struct server *other_srv;
6345
6346 if (newsrv->puid)
6347 continue;
6348
6349 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6350 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6351 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6352 newsrv->conf.file, newsrv->conf.line,
6353 proxy_type_str(curproxy), curproxy->id,
6354 newsrv->id, other_srv->conf.line);
6355 break;
6356 }
6357 }
6358 }
6359
Willy Tarreaudd701652010-05-25 23:03:02 +02006360 /* assign automatic UIDs to servers which don't have one yet */
6361 next_id = 1;
6362 newsrv = curproxy->srv;
6363 while (newsrv != NULL) {
6364 if (!newsrv->puid) {
6365 /* server ID not set, use automatic numbering with first
6366 * spare entry starting with next_svid.
6367 */
6368 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6369 newsrv->conf.id.key = newsrv->puid = next_id;
6370 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6371 }
6372 next_id++;
6373 newsrv = newsrv->next;
6374 }
6375
Willy Tarreau20697042007-11-15 23:26:18 +01006376 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006377 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378
Willy Tarreau62c3be22012-01-20 13:12:32 +01006379 /*
6380 * If this server supports a maxconn parameter, it needs a dedicated
6381 * tasks to fill the emptied slots when a connection leaves.
6382 * Also, resolve deferred tracking dependency if needed.
6383 */
6384 newsrv = curproxy->srv;
6385 while (newsrv != NULL) {
6386 if (newsrv->minconn > newsrv->maxconn) {
6387 /* Only 'minconn' was specified, or it was higher than or equal
6388 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6389 * this will avoid further useless expensive computations.
6390 */
6391 newsrv->maxconn = newsrv->minconn;
6392 } else if (newsrv->maxconn && !newsrv->minconn) {
6393 /* minconn was not specified, so we set it to maxconn */
6394 newsrv->minconn = newsrv->maxconn;
6395 }
6396
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006397#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006398 if (newsrv->use_ssl || newsrv->check.use_ssl)
6399 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006400#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006401
Willy Tarreau2f075e92013-12-03 11:11:34 +01006402 /* set the check type on the server */
6403 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6404
Willy Tarreau62c3be22012-01-20 13:12:32 +01006405 if (newsrv->trackit) {
6406 struct proxy *px;
6407 struct server *srv;
6408 char *pname, *sname;
6409
6410 pname = newsrv->trackit;
6411 sname = strrchr(pname, '/');
6412
6413 if (sname)
6414 *sname++ = '\0';
6415 else {
6416 sname = pname;
6417 pname = NULL;
6418 }
6419
6420 if (pname) {
6421 px = findproxy(pname, PR_CAP_BE);
6422 if (!px) {
6423 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6424 proxy_type_str(curproxy), curproxy->id,
6425 newsrv->id, pname);
6426 cfgerr++;
6427 goto next_srv;
6428 }
6429 } else
6430 px = curproxy;
6431
6432 srv = findserver(px, sname);
6433 if (!srv) {
6434 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6435 proxy_type_str(curproxy), curproxy->id,
6436 newsrv->id, sname);
6437 cfgerr++;
6438 goto next_srv;
6439 }
6440
Willy Tarreauff5ae352013-12-11 20:36:34 +01006441 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006442 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6443 "tracking as it does not have checks enabled.\n",
6444 proxy_type_str(curproxy), curproxy->id,
6445 newsrv->id, px->id, srv->id);
6446 cfgerr++;
6447 goto next_srv;
6448 }
6449
6450 if (curproxy != px &&
6451 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6452 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6453 "tracking: disable-on-404 option inconsistency.\n",
6454 proxy_type_str(curproxy), curproxy->id,
6455 newsrv->id, px->id, srv->id);
6456 cfgerr++;
6457 goto next_srv;
6458 }
6459
6460 /* if the other server is forced disabled, we have to do the same here */
6461 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006462 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006463 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006464 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006465 }
6466
6467 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006468 newsrv->tracknext = srv->trackers;
6469 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006470
6471 free(newsrv->trackit);
6472 newsrv->trackit = NULL;
6473 }
6474 next_srv:
6475 newsrv = newsrv->next;
6476 }
6477
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006478 /* We have to initialize the server lookup mechanism depending
6479 * on what LB algorithm was choosen.
6480 */
6481
6482 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6483 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6484 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006485 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6486 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6487 init_server_map(curproxy);
6488 } else {
6489 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6490 fwrr_init_server_groups(curproxy);
6491 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006492 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006493
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006494 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006495 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6496 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6497 fwlc_init_server_tree(curproxy);
6498 } else {
6499 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6500 fas_init_server_tree(curproxy);
6501 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006502 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006503
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006504 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006505 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6506 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6507 chash_init_server_tree(curproxy);
6508 } else {
6509 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6510 init_server_map(curproxy);
6511 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006512 break;
6513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006514
6515 if (curproxy->options & PR_O_LOGASAP)
6516 curproxy->to_log &= ~LW_BYTES;
6517
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006518 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006519 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006520 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6521 proxy_type_str(curproxy), curproxy->id);
6522 err_code |= ERR_WARN;
6523 }
6524
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006525 if (curproxy->mode != PR_MODE_HTTP) {
6526 int optnum;
6527
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006528 if (curproxy->uri_auth) {
6529 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6530 proxy_type_str(curproxy), curproxy->id);
6531 err_code |= ERR_WARN;
6532 curproxy->uri_auth = NULL;
6533 }
6534
Willy Tarreau87cf5142011-08-19 22:57:24 +02006535 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006536 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6537 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6538 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006539 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006540 }
6541
6542 if (curproxy->options & PR_O_ORGTO) {
6543 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6544 "originalto", proxy_type_str(curproxy), curproxy->id);
6545 err_code |= ERR_WARN;
6546 curproxy->options &= ~PR_O_ORGTO;
6547 }
6548
6549 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6550 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6551 (curproxy->cap & cfg_opts[optnum].cap) &&
6552 (curproxy->options & cfg_opts[optnum].val)) {
6553 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6554 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6555 err_code |= ERR_WARN;
6556 curproxy->options &= ~cfg_opts[optnum].val;
6557 }
6558 }
6559
6560 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6561 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6562 (curproxy->cap & cfg_opts2[optnum].cap) &&
6563 (curproxy->options2 & cfg_opts2[optnum].val)) {
6564 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6565 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6566 err_code |= ERR_WARN;
6567 curproxy->options2 &= ~cfg_opts2[optnum].val;
6568 }
6569 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006570
Pieter Baauwd551fb52013-05-08 22:49:23 +02006571#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006572 if (curproxy->conn_src.bind_hdr_occ) {
6573 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006574 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006575 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006576 err_code |= ERR_WARN;
6577 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006578#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006579 }
6580
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006582 * ensure that we're not cross-dressing a TCP server into HTTP.
6583 */
6584 newsrv = curproxy->srv;
6585 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006586 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006587 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6588 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006589 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006590 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006591
Willy Tarreau0cec3312011-10-31 13:49:26 +01006592 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6593 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6594 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6595 err_code |= ERR_WARN;
6596 }
6597
Willy Tarreau82ffa392013-08-13 17:19:08 +02006598 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6599 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6600 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6601 err_code |= ERR_WARN;
6602 }
6603
Pieter Baauwd551fb52013-05-08 22:49:23 +02006604#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006605 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6606 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006607 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 +01006608 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006609 err_code |= ERR_WARN;
6610 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006611#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006612 newsrv = newsrv->next;
6613 }
6614
Willy Tarreauc1a21672009-08-16 22:37:44 +02006615 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006616 if (!curproxy->accept)
6617 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006618
Willy Tarreauc1a21672009-08-16 22:37:44 +02006619 if (curproxy->tcp_req.inspect_delay ||
6620 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006621 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006622
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006623 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006624 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006625 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006626 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006627
6628 /* both TCP and HTTP must check switching rules */
6629 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6630 }
6631
6632 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006633 if (curproxy->tcp_req.inspect_delay ||
6634 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6635 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6636
Emeric Brun97679e72010-09-23 17:56:44 +02006637 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6638 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6639
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006640 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006641 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006642 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006643 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006644
6645 /* If the backend does requires RDP cookie persistence, we have to
6646 * enable the corresponding analyser.
6647 */
6648 if (curproxy->options2 & PR_O2_RDPC_PRST)
6649 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6650 }
6651
Emeric Brunc52962f2012-11-15 18:28:02 +01006652#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006653 /* Configure SSL for each bind line.
6654 * Note: if configuration fails at some point, the ->ctx member
6655 * remains NULL so that listeners can later detach.
6656 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006657 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006658 if (!bind_conf->is_ssl) {
6659 if (bind_conf->default_ctx) {
6660 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6661 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6662 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006663 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006664 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006665 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006666 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006667 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006668 cfgerr++;
6669 continue;
6670 }
6671
Emeric Brun4b3091e2012-09-24 15:48:52 +02006672 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006673 Alert("Unable to allocate SSL session cache.\n");
6674 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006675 continue;
6676 }
6677
Emeric Brunfc0421f2012-09-07 17:30:07 +02006678 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006679 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006680 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006681#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006682
Willy Tarreaue6b98942007-10-29 01:09:36 +01006683 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006684 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006685 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006686 if (!listener->luid) {
6687 /* listener ID not set, use automatic numbering with first
6688 * spare entry starting with next_luid.
6689 */
6690 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6691 listener->conf.id.key = listener->luid = next_id;
6692 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006693 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006694 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006695
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006696 /* enable separate counters */
6697 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6698 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006699 if (!listener->name)
6700 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006701 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006702
Willy Tarreaue6b98942007-10-29 01:09:36 +01006703 if (curproxy->options & PR_O_TCP_NOLING)
6704 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006705 if (!listener->maxconn)
6706 listener->maxconn = curproxy->maxconn;
6707 if (!listener->backlog)
6708 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006709 if (!listener->maxaccept)
6710 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6711
6712 /* we want to have an optimal behaviour on single process mode to
6713 * maximize the work at once, but in multi-process we want to keep
6714 * some fairness between processes, so we target half of the max
6715 * number of events to be balanced over all the processes the proxy
6716 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6717 * used to disable the limit.
6718 */
6719 if (listener->maxaccept > 0) {
6720 if (nbproc > 1)
6721 listener->maxaccept = (listener->maxaccept + 1) / 2;
6722 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6723 }
6724
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006725 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006726 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006727 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006728 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006729
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006730 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6731 listener->options |= LI_O_TCP_RULES;
6732
Willy Tarreaude3041d2010-05-31 10:56:17 +02006733 if (curproxy->mon_mask.s_addr)
6734 listener->options |= LI_O_CHK_MONNET;
6735
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006736 /* smart accept mode is automatic in HTTP mode */
6737 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006738 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006739 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6740 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006741 }
6742
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006743 /* Release unused SSL configs */
6744 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6745 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006746 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006747#ifdef USE_OPENSSL
6748 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006749 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006750 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006751 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006752 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006753#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006754 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006755
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006756 /* Check multi-process mode compatibility for the current proxy */
6757 if (global.nbproc > 1) {
6758 int nbproc = 0;
6759 if (curproxy->bind_proc) {
6760 int proc;
6761 for (proc = 0; proc < global.nbproc; proc++) {
6762 if (curproxy->bind_proc & (1 << proc)) {
6763 nbproc++;
6764 }
6765 }
6766 } else {
6767 nbproc = global.nbproc;
6768 }
6769 if (curproxy->table.peers.name) {
6770 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6771 curproxy->id);
6772 cfgerr++;
6773 }
6774 if (nbproc > 1) {
6775 if (curproxy->uri_auth) {
6776 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6777 curproxy->id);
6778 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6779 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6780 curproxy->id);
6781 }
6782 }
6783 if (curproxy->appsession_name) {
6784 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6785 curproxy->id);
6786 }
6787 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6788 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6789 curproxy->id);
6790 }
6791 }
6792 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006793
6794 /* create the task associated with the proxy */
6795 curproxy->task = task_new();
6796 if (curproxy->task) {
6797 curproxy->task->context = curproxy;
6798 curproxy->task->process = manage_proxy;
6799 /* no need to queue, it will be done automatically if some
6800 * listener gets limited.
6801 */
6802 curproxy->task->expire = TICK_ETERNITY;
6803 } else {
6804 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6805 curproxy->id);
6806 cfgerr++;
6807 }
6808
Willy Tarreaubaaee002006-06-26 02:48:02 +02006809 curproxy = curproxy->next;
6810 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006811
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006812 /* Check multi-process mode compatibility */
6813 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006814 if (global.stats_fe && !global.stats_fe->bind_proc) {
6815 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 +01006816 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006817 }
6818
6819 /* automatically compute fullconn if not set. We must not do it in the
6820 * loop above because cross-references are not yet fully resolved.
6821 */
6822 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6823 /* If <fullconn> is not set, let's set it to 10% of the sum of
6824 * the possible incoming frontend's maxconns.
6825 */
6826 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6827 struct proxy *fe;
6828 int total = 0;
6829
6830 /* sum up the number of maxconns of frontends which
6831 * reference this backend at least once or which are
6832 * the same one ('listen').
6833 */
6834 for (fe = proxy; fe; fe = fe->next) {
6835 struct switching_rule *rule;
6836 struct hdr_exp *exp;
6837 int found = 0;
6838
6839 if (!(fe->cap & PR_CAP_FE))
6840 continue;
6841
6842 if (fe == curproxy) /* we're on a "listen" instance */
6843 found = 1;
6844
6845 if (fe->defbe.be == curproxy) /* "default_backend" */
6846 found = 1;
6847
6848 /* check if a "use_backend" rule matches */
6849 if (!found) {
6850 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006851 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006852 found = 1;
6853 break;
6854 }
6855 }
6856 }
6857
6858 /* check if a "reqsetbe" rule matches */
6859 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6860 if (exp->action == ACT_SETBE &&
6861 (struct proxy *)exp->replace == curproxy) {
6862 found = 1;
6863 break;
6864 }
6865 }
6866
6867 /* now we've checked all possible ways to reference a backend
6868 * from a frontend.
6869 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006870 if (!found)
6871 continue;
6872 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006873 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006874 /* we have the sum of the maxconns in <total>. We only
6875 * keep 10% of that sum to set the default fullconn, with
6876 * a hard minimum of 1 (to avoid a divide by zero).
6877 */
6878 curproxy->fullconn = (total + 9) / 10;
6879 if (!curproxy->fullconn)
6880 curproxy->fullconn = 1;
6881 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006882 }
6883
Willy Tarreau056f5682010-06-06 15:51:11 +02006884 /* initialize stick-tables on backend capable proxies. This must not
6885 * be done earlier because the data size may be discovered while parsing
6886 * other proxies.
6887 */
Godbach9703e662013-12-11 21:11:41 +08006888 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006889 if (curproxy->state == PR_STSTOPPED)
6890 continue;
6891
Godbach9703e662013-12-11 21:11:41 +08006892 if (!stktable_init(&curproxy->table)) {
6893 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6894 cfgerr++;
6895 }
6896 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006897
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006898 /*
6899 * Recount currently required checks.
6900 */
6901
6902 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6903 int optnum;
6904
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006905 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6906 if (curproxy->options & cfg_opts[optnum].val)
6907 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006908
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006909 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6910 if (curproxy->options2 & cfg_opts2[optnum].val)
6911 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006912 }
6913
Willy Tarreau122541c2011-09-07 21:24:49 +02006914 if (peers) {
6915 struct peers *curpeers = peers, **last;
6916 struct peer *p, *pb;
6917
6918 /* Remove all peers sections which don't have a valid listener.
6919 * This can happen when a peers section is never referenced and
6920 * does not contain a local peer.
6921 */
6922 last = &peers;
6923 while (*last) {
6924 curpeers = *last;
6925 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01006926 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02006927 last = &curpeers->next;
6928 continue;
6929 }
6930
6931 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6932 curpeers->id, localpeer);
6933
6934 p = curpeers->remote;
6935 while (p) {
6936 pb = p->next;
6937 free(p->id);
6938 free(p);
6939 p = pb;
6940 }
6941
6942 /* Destroy and unlink this curpeers section.
6943 * Note: curpeers is backed up into *last.
6944 */
6945 free(curpeers->id);
6946 curpeers = curpeers->next;
6947 free(*last);
6948 *last = curpeers;
6949 }
6950 }
6951
Willy Tarreau34eb6712011-10-24 18:15:04 +02006952 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006953 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006954 MEM_F_SHARED);
6955
Willy Tarreaubb925012009-07-23 13:36:36 +02006956 if (cfgerr > 0)
6957 err_code |= ERR_ALERT | ERR_FATAL;
6958 out:
6959 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006960}
6961
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006962/*
6963 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6964 * parsing sessions.
6965 */
6966void cfg_register_keywords(struct cfg_kw_list *kwl)
6967{
6968 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6969}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006970
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006971/*
6972 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6973 */
6974void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6975{
6976 LIST_DEL(&kwl->list);
6977 LIST_INIT(&kwl->list);
6978}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006980/* this function register new section in the haproxy configuration file.
6981 * <section_name> is the name of this new section and <section_parser>
6982 * is the called parser. If two section declaration have the same name,
6983 * only the first declared is used.
6984 */
6985int cfg_register_section(char *section_name,
6986 int (*section_parser)(const char *, int, char **, int))
6987{
6988 struct cfg_section *cs;
6989
6990 cs = calloc(1, sizeof(*cs));
6991 if (!cs) {
6992 Alert("register section '%s': out of memory.\n", section_name);
6993 return 0;
6994 }
6995
6996 cs->section_name = section_name;
6997 cs->section_parser = section_parser;
6998
6999 LIST_ADDQ(&sections, &cs->list);
7000
7001 return 1;
7002}
7003
Willy Tarreaubaaee002006-06-26 02:48:02 +02007004/*
7005 * Local variables:
7006 * c-indent-level: 8
7007 * c-basic-offset: 8
7008 * End:
7009 */