blob: 19c5599572b2b43beeeb7a7e4d1e8d9cff59f41c [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
Willy Tarreau5002f572014-04-23 01:32:02 +0200323/* Report a warning if a rule is placed after an 'http_request' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
327{
328 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
Willy Tarreau61d18892009-03-31 10:49:21 +0200336/* Report a warning if a rule is placed after a reqrewrite rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
341 if (proxy->req_exp) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a reqadd rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100354 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a redirect rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a 'use_backend' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
Willy Tarreauee445d92014-04-23 01:39:04 +0200388/* Report a warning if a rule is placed after a 'use-server' rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
391int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
392{
393 if (!LIST_ISEMPTY(&proxy->server_rules)) {
394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
Willy Tarreau61d18892009-03-31 10:49:21 +0200401/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
Willy Tarreau5002f572014-04-23 01:32:02 +0200404 return warnif_rule_after_http_req(proxy, file, line, arg) ||
405 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
406 warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200408 warnif_rule_after_use_backend(proxy, file, line, arg) ||
409 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200410}
411
412/* report a warning if an http-request rule is dangerously placed */
413int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
414{
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200420}
421
422/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
425 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
426 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200427 warnif_rule_after_use_backend(proxy, file, line, arg) ||
428 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200429}
430
431/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100432int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200433{
434 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a redirect rule is dangerously placed */
440int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
443 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200444}
445
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446/* Report it if a request ACL condition uses some keywords that are incompatible
447 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
448 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
449 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100451static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100453 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200454 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100457 return 0;
458
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100459 acl = acl_cond_conflicts(cond, where);
460 if (acl) {
461 if (acl->name && *acl->name)
462 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
463 file, line, acl->name, sample_ckp_names(where));
464 else
465 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200466 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100467 return ERR_WARN;
468 }
469 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100470 return 0;
471
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100472 if (acl->name && *acl->name)
473 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200474 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100475 else
476 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200477 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100478 return ERR_WARN;
479}
480
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 * parse a line in a <global> section. Returns the error code, 0 if OK, or
483 * any combination of :
484 * - ERR_ABORT: must abort ASAP
485 * - ERR_FATAL: we can continue parsing but not start the service
486 * - ERR_WARN: a warning has been emitted
487 * - ERR_ALERT: an alert has been emitted
488 * Only the two first ones can stop processing, the two others are just
489 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200491int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492{
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200494 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (!strcmp(args[0], "global")) { /* new section */
497 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200500 else if (!strcmp(args[0], "ca-base")) {
501#ifdef USE_OPENSSL
502 if (global.ca_base != NULL) {
503 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT;
505 goto out;
506 }
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 global.ca_base = strdup(args[1]);
513#else
514 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517#endif
518 }
519 else if (!strcmp(args[0], "crt-base")) {
520#ifdef USE_OPENSSL
521 if (global.crt_base != NULL) {
522 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT;
524 goto out;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 global.crt_base = strdup(args[1]);
532#else
533 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536#endif
537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "daemon")) {
539 global.mode |= MODE_DAEMON;
540 }
541 else if (!strcmp(args[0], "debug")) {
542 global.mode |= MODE_DEBUG;
543 }
544 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100545 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200547 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100548 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100551 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100553 else if (!strcmp(args[0], "nosplice")) {
554 global.tune.options &= ~GTUNE_USE_SPLICE;
555 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200556 else if (!strcmp(args[0], "nogetaddrinfo")) {
557 global.tune.options &= ~GTUNE_USE_GAI;
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 else if (!strcmp(args[0], "quiet")) {
560 global.mode |= MODE_QUIET;
561 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200562 else if (!strcmp(args[0], "tune.maxpollevents")) {
563 if (global.tune.maxpollevents != 0) {
564 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200565 err_code |= ERR_ALERT;
566 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200567 }
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 }
573 global.tune.maxpollevents = atol(args[1]);
574 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100575 else if (!strcmp(args[0], "tune.maxaccept")) {
576 if (global.tune.maxaccept != 0) {
577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100580 }
581 if (*(args[1]) == 0) {
582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 }
586 global.tune.maxaccept = atol(args[1]);
587 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200588 else if (!strcmp(args[0], "tune.chksize")) {
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.chksize = atol(args[1]);
595 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200596#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100597 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.sslcachesize = atol(args[1]);
604 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100605 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
606 unsigned int ssllifetime;
607 const char *res;
608
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
613 }
614
615 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
616 if (res) {
617 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
618 file, linenum, *res, args[0]);
619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
621 }
622
623 global.tune.ssllifetime = ssllifetime;
624 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100625 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630 }
631 global.tune.ssl_max_record = atol(args[1]);
632 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200633#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200634 else if (!strcmp(args[0], "tune.bufsize")) {
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.bufsize = atol(args[1]);
641 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
642 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100643 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100644 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200645 }
646 else if (!strcmp(args[0], "tune.maxrewrite")) {
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 global.tune.maxrewrite = atol(args[1]);
653 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
654 global.tune.maxrewrite = global.tune.bufsize / 2;
655 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100656 else if (!strcmp(args[0], "tune.idletimer")) {
657 unsigned int idle;
658 const char *res;
659
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
664 }
665
666 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
667 if (res) {
668 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
669 file, linenum, *res, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673
674 if (idle > 65535) {
675 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT | ERR_FATAL;
677 goto out;
678 }
679 global.tune.idle_timer = idle;
680 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100681 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
682 if (global.tune.client_rcvbuf != 0) {
683 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
684 err_code |= ERR_ALERT;
685 goto out;
686 }
687 if (*(args[1]) == 0) {
688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
691 }
692 global.tune.client_rcvbuf = atol(args[1]);
693 }
694 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
695 if (global.tune.server_rcvbuf != 0) {
696 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT;
698 goto out;
699 }
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.server_rcvbuf = atol(args[1]);
706 }
707 else if (!strcmp(args[0], "tune.sndbuf.client")) {
708 if (global.tune.client_sndbuf != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT;
711 goto out;
712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718 global.tune.client_sndbuf = atol(args[1]);
719 }
720 else if (!strcmp(args[0], "tune.sndbuf.server")) {
721 if (global.tune.server_sndbuf != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT;
724 goto out;
725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.server_sndbuf = atol(args[1]);
732 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200733 else if (!strcmp(args[0], "tune.pipesize")) {
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739 global.tune.pipesize = atol(args[1]);
740 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100741 else if (!strcmp(args[0], "tune.http.cookielen")) {
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747 global.tune.cookie_len = atol(args[1]) + 1;
748 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200749 else if (!strcmp(args[0], "tune.http.maxhdr")) {
750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.max_http_hdr = atol(args[1]);
756 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100757 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
758#ifdef USE_ZLIB
759 if (*args[1]) {
760 global.tune.zlibmemlevel = atoi(args[1]);
761 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
762 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
763 file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 } else {
768 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
769 file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773#else
774 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777#endif
778 }
779 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
780#ifdef USE_ZLIB
781 if (*args[1]) {
782 global.tune.zlibwindowsize = atoi(args[1]);
783 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
784 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
785 file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789 } else {
790 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
791 file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795#else
796 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799#endif
800 }
William Lallemandf3747832012-11-09 12:33:10 +0100801 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
802 if (*args[1]) {
803 global.tune.comp_maxlevel = atoi(args[1]);
804 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
805 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
806 file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 } else {
811 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
812 file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 else if (!strcmp(args[0], "uid")) {
818 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200819 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT;
821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 global.uid = atol(args[1]);
829 }
830 else if (!strcmp(args[0], "gid")) {
831 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200832 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200833 err_code |= ERR_ALERT;
834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 global.gid = atol(args[1]);
842 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200843 /* user/group name handling */
844 else if (!strcmp(args[0], "user")) {
845 struct passwd *ha_user;
846 if (global.uid != 0) {
847 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200848 err_code |= ERR_ALERT;
849 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200850 }
851 errno = 0;
852 ha_user = getpwnam(args[1]);
853 if (ha_user != NULL) {
854 global.uid = (int)ha_user->pw_uid;
855 }
856 else {
857 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 +0200858 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200859 }
860 }
861 else if (!strcmp(args[0], "group")) {
862 struct group *ha_group;
863 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200864 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200865 err_code |= ERR_ALERT;
866 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200867 }
868 errno = 0;
869 ha_group = getgrnam(args[1]);
870 if (ha_group != NULL) {
871 global.gid = (int)ha_group->gr_gid;
872 }
873 else {
874 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 +0200875 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200876 }
877 }
878 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 if (*(args[1]) == 0) {
881 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 }
885 global.nbproc = atol(args[1]);
886 }
887 else if (!strcmp(args[0], "maxconn")) {
888 if (global.maxconn != 0) {
889 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
898 global.maxconn = atol(args[1]);
899#ifdef SYSTEM_MAXCONN
900 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
901 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);
902 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905#endif /* SYSTEM_MAXCONN */
906 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200907 else if (!strcmp(args[0], "maxsslconn")) {
908#ifdef USE_OPENSSL
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
913 }
914 global.maxsslconn = atol(args[1]);
915#else
Emeric Brun0914df82012-10-02 18:45:42 +0200916 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200919#endif
920 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100921 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
922#ifdef USE_OPENSSL
923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 free(global.listen_default_ciphers);
929 global.listen_default_ciphers = strdup(args[1]);
930#else
931 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
934#endif
935 }
936 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
937#ifdef USE_OPENSSL
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 free(global.connect_default_ciphers);
944 global.connect_default_ciphers = strdup(args[1]);
945#else
946 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
949#endif
950 }
Emeric Brun850efd52014-01-29 12:24:34 +0100951 else if (!strcmp(args[0], "ssl-server-verify")) {
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957 if (strcmp(args[1],"none") == 0)
958 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
959 else if (strcmp(args[1],"required") == 0)
960 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
961 else {
962 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200967 else if (!strcmp(args[0], "maxconnrate")) {
968 if (global.cps_lim != 0) {
969 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
970 err_code |= ERR_ALERT;
971 goto out;
972 }
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978 global.cps_lim = atol(args[1]);
979 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200980 else if (!strcmp(args[0], "maxsessrate")) {
981 if (global.sps_lim != 0) {
982 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
983 err_code |= ERR_ALERT;
984 goto out;
985 }
986 if (*(args[1]) == 0) {
987 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
990 }
991 global.sps_lim = atol(args[1]);
992 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200993 else if (!strcmp(args[0], "maxsslrate")) {
994 if (global.ssl_lim != 0) {
995 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
996 err_code |= ERR_ALERT;
997 goto out;
998 }
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 global.ssl_lim = atol(args[1]);
1005 }
William Lallemandd85f9172012-11-09 17:05:39 +01001006 else if (!strcmp(args[0], "maxcomprate")) {
1007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 global.comp_rate_lim = atoi(args[1]) * 1024;
1013 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001014 else if (!strcmp(args[0], "maxpipes")) {
1015 if (global.maxpipes != 0) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT;
1018 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001019 }
1020 if (*(args[1]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001024 }
1025 global.maxpipes = atol(args[1]);
1026 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001027 else if (!strcmp(args[0], "maxzlibmem")) {
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
William Lallemande3a7d992012-11-20 11:25:20 +01001033 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001034 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001035 else if (!strcmp(args[0], "maxcompcpuusage")) {
1036 if (*(args[1]) == 0) {
1037 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001042 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001043 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047}
1048
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 else if (!strcmp(args[0], "ulimit-n")) {
1050 if (global.rlimit_nofile != 0) {
1051 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT;
1053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
1060 global.rlimit_nofile = atol(args[1]);
1061 }
1062 else if (!strcmp(args[0], "chroot")) {
1063 if (global.chroot != NULL) {
1064 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001065 err_code |= ERR_ALERT;
1066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 }
1068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 global.chroot = strdup(args[1]);
1074 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001075 else if (!strcmp(args[0], "description")) {
1076 int i, len=0;
1077 char *d;
1078
1079 if (!*args[1]) {
1080 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1081 file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085
Willy Tarreau348acfe2014-04-14 15:00:39 +02001086 for (i = 1; *args[i]; i++)
1087 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001088
1089 if (global.desc)
1090 free(global.desc);
1091
1092 global.desc = d = (char *)calloc(1, len);
1093
Willy Tarreau348acfe2014-04-14 15:00:39 +02001094 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1095 for (i = 2; *args[i]; i++)
1096 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097 }
1098 else if (!strcmp(args[0], "node")) {
1099 int i;
1100 char c;
1101
1102 for (i=0; args[1][i]; i++) {
1103 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001104 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1105 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001106 break;
1107 }
1108
1109 if (!i || args[1][i]) {
1110 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1111 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1112 file, linenum, args[0]);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116
1117 if (global.node)
1118 free(global.node);
1119
1120 global.node = strdup(args[1]);
1121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 else if (!strcmp(args[0], "pidfile")) {
1123 if (global.pidfile != NULL) {
1124 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 err_code |= ERR_ALERT;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 global.pidfile = strdup(args[1]);
1134 }
Emeric Bruned760922010-10-22 17:59:25 +02001135 else if (!strcmp(args[0], "unix-bind")) {
1136 int cur_arg = 1;
1137 while (*(args[cur_arg])) {
1138 if (!strcmp(args[cur_arg], "prefix")) {
1139 if (global.unix_bind.prefix != NULL) {
1140 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1141 err_code |= ERR_ALERT;
1142 cur_arg += 2;
1143 continue;
1144 }
1145
1146 if (*(args[cur_arg+1]) == 0) {
1147 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
1150 }
1151 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1152 cur_arg += 2;
1153 continue;
1154 }
1155
1156 if (!strcmp(args[cur_arg], "mode")) {
1157
1158 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1159 cur_arg += 2;
1160 continue;
1161 }
1162
1163 if (!strcmp(args[cur_arg], "uid")) {
1164
1165 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1166 cur_arg += 2;
1167 continue;
1168 }
1169
1170 if (!strcmp(args[cur_arg], "gid")) {
1171
1172 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1173 cur_arg += 2;
1174 continue;
1175 }
1176
1177 if (!strcmp(args[cur_arg], "user")) {
1178 struct passwd *user;
1179
1180 user = getpwnam(args[cur_arg + 1]);
1181 if (!user) {
1182 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1183 file, linenum, args[0], args[cur_arg + 1 ]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 global.unix_bind.ux.uid = user->pw_uid;
1189 cur_arg += 2;
1190 continue;
1191 }
1192
1193 if (!strcmp(args[cur_arg], "group")) {
1194 struct group *group;
1195
1196 group = getgrnam(args[cur_arg + 1]);
1197 if (!group) {
1198 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1199 file, linenum, args[0], args[cur_arg + 1 ]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203
1204 global.unix_bind.ux.gid = group->gr_gid;
1205 cur_arg += 2;
1206 continue;
1207 }
1208
Willy Tarreaub48f9582011-09-05 01:17:06 +02001209 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001210 file, linenum, args[0]);
1211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
1213 }
1214 }
William Lallemand0f99e342011-10-12 17:50:54 +02001215 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1216 /* delete previous herited or defined syslog servers */
1217 struct logsrv *back;
1218 struct logsrv *tmp;
1219
1220 if (*(args[1]) != 0) {
1221 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225
1226 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1227 LIST_DEL(&tmp->list);
1228 free(tmp);
1229 }
1230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001232 struct sockaddr_storage *sk;
1233 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001234 struct logsrv *logsrv;
1235
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 if (*(args[1]) == 0 || *(args[2]) == 0) {
1237 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 }
William Lallemand0f99e342011-10-12 17:50:54 +02001241
1242 logsrv = calloc(1, sizeof(struct logsrv));
1243
1244 logsrv->facility = get_log_facility(args[2]);
1245 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001247 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001248 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 }
1250
William Lallemand0f99e342011-10-12 17:50:54 +02001251 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001253 logsrv->level = get_log_level(args[3]);
1254 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001257 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 }
1260
William Lallemand0f99e342011-10-12 17:50:54 +02001261 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001262 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001263 logsrv->minlvl = get_log_level(args[4]);
1264 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001265 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001266 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001267 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001268 }
1269 }
1270
Willy Tarreau902636f2013-03-10 19:44:48 +01001271 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001272 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001273 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001274 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001275 free(logsrv);
1276 goto out;
1277 }
1278 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001279
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001280 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001281 if (port1 != port2) {
1282 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1283 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001284 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001285 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001286 goto out;
1287 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001288
William Lallemand0f99e342011-10-12 17:50:54 +02001289 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001290 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001291 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293
William Lallemand0f99e342011-10-12 17:50:54 +02001294 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001295 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001296 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1297 char *name;
1298 int len;
1299
1300 if (global.log_send_hostname != NULL) {
1301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1302 err_code |= ERR_ALERT;
1303 goto out;
1304 }
1305
1306 if (*(args[1]))
1307 name = args[1];
1308 else
1309 name = hostname;
1310
1311 len = strlen(name);
1312
1313 /* We'll add a space after the name to respect the log format */
1314 free(global.log_send_hostname);
1315 global.log_send_hostname = malloc(len + 2);
1316 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1317 }
Kevinm48936af2010-12-22 16:08:21 +00001318 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1319 if (*(args[1]) == 0) {
1320 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
1323 }
1324 free(global.log_tag);
1325 global.log_tag = strdup(args[1]);
1326 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001327 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1328 if (global.spread_checks != 0) {
1329 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001330 err_code |= ERR_ALERT;
1331 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001332 }
1333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001337 }
1338 global.spread_checks = atol(args[1]);
1339 if (global.spread_checks < 0 || global.spread_checks > 50) {
1340 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001344 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1345#ifdef USE_CPU_AFFINITY
1346 int cur_arg, i;
1347 unsigned int proc = 0;
1348 unsigned long cpus = 0;
1349
1350 if (strcmp(args[1], "all") == 0)
1351 proc = 0xFFFFFFFF;
1352 else if (strcmp(args[1], "odd") == 0)
1353 proc = 0x55555555;
1354 else if (strcmp(args[1], "even") == 0)
1355 proc = 0xAAAAAAAA;
1356 else {
1357 proc = atoi(args[1]);
1358 if (proc >= 1 && proc <= 32)
1359 proc = 1 << (proc - 1);
1360 }
1361
1362 if (!proc || !*args[2]) {
1363 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",
1364 file, linenum, args[0]);
1365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
1367 }
1368
1369 cur_arg = 2;
1370 while (*args[cur_arg]) {
1371 unsigned int low, high;
1372
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001373 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001374 char *dash = strchr(args[cur_arg], '-');
1375
1376 low = high = str2uic(args[cur_arg]);
1377 if (dash)
1378 high = str2uic(dash + 1);
1379
1380 if (high < low) {
1381 unsigned int swap = low;
1382 low = high;
1383 high = swap;
1384 }
1385
1386 if (low < 0 || high >= sizeof(long) * 8) {
1387 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1388 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1389 err_code |= ERR_ALERT | ERR_FATAL;
1390 goto out;
1391 }
1392
1393 while (low <= high)
1394 cpus |= 1UL << low++;
1395 }
1396 else {
1397 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1398 file, linenum, args[0], args[cur_arg]);
1399 err_code |= ERR_ALERT | ERR_FATAL;
1400 goto out;
1401 }
1402 cur_arg++;
1403 }
1404 for (i = 0; i < 32; i++)
1405 if (proc & (1 << i))
1406 global.cpu_map[i] = cpus;
1407#else
1408 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1409 err_code |= ERR_ALERT | ERR_FATAL;
1410 goto out;
1411#endif
1412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001414 struct cfg_kw_list *kwl;
1415 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001416 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001417
1418 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1419 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1420 if (kwl->kw[index].section != CFG_GLOBAL)
1421 continue;
1422 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001423 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001424 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001425 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001426 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001427 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001428 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001429 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_WARN;
1431 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001432 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001433 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001434 }
1435 }
1436 }
1437
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001439 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001441
Willy Tarreau058e9072009-07-20 09:30:05 +02001442 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001443 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001444 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445}
1446
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001447void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001449 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 defproxy.mode = PR_MODE_TCP;
1451 defproxy.state = PR_STNEW;
1452 defproxy.maxconn = cfg_maxpconn;
1453 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001454
Simon Horman66183002013-02-23 10:16:43 +09001455 defproxy.defsrv.check.inter = DEF_CHKINTR;
1456 defproxy.defsrv.check.fastinter = 0;
1457 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001458 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1459 defproxy.defsrv.agent.fastinter = 0;
1460 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001461 defproxy.defsrv.check.rise = DEF_RISETIME;
1462 defproxy.defsrv.check.fall = DEF_FALLTIME;
1463 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1464 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001465 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001466 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001467 defproxy.defsrv.maxqueue = 0;
1468 defproxy.defsrv.minconn = 0;
1469 defproxy.defsrv.maxconn = 0;
1470 defproxy.defsrv.slowstart = 0;
1471 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1472 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1473 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474}
1475
Willy Tarreauade5ec42010-01-28 19:33:49 +01001476
1477static int create_cond_regex_rule(const char *file, int line,
1478 struct proxy *px, int dir, int action, int flags,
1479 const char *cmd, const char *reg, const char *repl,
1480 const char **cond_start)
1481{
1482 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001483 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001484 const char *err;
1485 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001486 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001487
1488 if (px == &defproxy) {
1489 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto err;
1492 }
1493
1494 if (*reg == 0) {
1495 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto err;
1498 }
1499
1500 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1501 err_code |= ERR_WARN;
1502
Willy Tarreau5321c422010-01-28 20:35:13 +01001503 if (cond_start &&
1504 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001505 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1506 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1507 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto err;
1510 }
1511 }
1512 else if (cond_start && **cond_start) {
1513 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1514 file, line, cmd, *cond_start);
1515 err_code |= ERR_ALERT | ERR_FATAL;
1516 goto err;
1517 }
1518
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001519 err_code |= warnif_cond_conflicts(cond,
1520 (dir == SMP_OPT_DIR_REQ) ?
1521 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1522 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1523 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001524
Willy Tarreauade5ec42010-01-28 19:33:49 +01001525 preg = calloc(1, sizeof(regex_t));
1526 if (!preg) {
1527 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1528 err_code = ERR_ALERT | ERR_FATAL;
1529 goto err;
1530 }
1531
1532 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1533 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1534 err_code = ERR_ALERT | ERR_FATAL;
1535 goto err;
1536 }
1537
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001538 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001539 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001540 if (repl && err) {
1541 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1542 file, line, cmd, *err);
1543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto err;
1545 }
1546
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001547 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001548 err_code |= ERR_WARN;
1549
Willy Tarreauf4068b62012-05-08 17:37:49 +02001550 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001551 return err_code;
1552 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001553 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001554 free(preg);
1555 return err_code;
1556}
1557
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001559 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001560 * Returns the error code, 0 if OK, or any combination of :
1561 * - ERR_ABORT: must abort ASAP
1562 * - ERR_FATAL: we can continue parsing but not start the service
1563 * - ERR_WARN: a warning has been emitted
1564 * - ERR_ALERT: an alert has been emitted
1565 * Only the two first ones can stop processing, the two others are just
1566 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001568int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1569{
1570 static struct peers *curpeers = NULL;
1571 struct peer *newpeer = NULL;
1572 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001573 struct bind_conf *bind_conf;
1574 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001575 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001576 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001577
1578 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001579 if (!*args[1]) {
1580 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001581 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001582 goto out;
1583 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001584
1585 err = invalid_char(args[1]);
1586 if (err) {
1587 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1588 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001589 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001590 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001591 }
1592
1593 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1594 /*
1595 * If there are two proxies with the same name only following
1596 * combinations are allowed:
1597 */
1598 if (strcmp(curpeers->id, args[1]) == 0) {
1599 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1600 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1601 err_code |= ERR_WARN;
1602 }
1603 }
1604
1605 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1606 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1607 err_code |= ERR_ALERT | ERR_ABORT;
1608 goto out;
1609 }
1610
1611 curpeers->next = peers;
1612 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001613 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001614 curpeers->conf.line = linenum;
1615 curpeers->last_change = now.tv_sec;
1616 curpeers->id = strdup(args[1]);
1617 }
1618 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001619 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001620 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001621 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001622
1623 if (!*args[2]) {
1624 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1625 file, linenum, args[0]);
1626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
1629
1630 err = invalid_char(args[1]);
1631 if (err) {
1632 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1633 file, linenum, *err, args[1]);
1634 err_code |= ERR_ALERT | ERR_FATAL;
1635 goto out;
1636 }
1637
1638 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1639 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1640 err_code |= ERR_ALERT | ERR_ABORT;
1641 goto out;
1642 }
1643
1644 /* the peers are linked backwards first */
1645 curpeers->count++;
1646 newpeer->next = curpeers->remote;
1647 curpeers->remote = newpeer;
1648 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001649 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001650 newpeer->conf.line = linenum;
1651
1652 newpeer->last_change = now.tv_sec;
1653 newpeer->id = strdup(args[1]);
1654
Willy Tarreau902636f2013-03-10 19:44:48 +01001655 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001656 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001657 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001660 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001661
1662 proto = protocol_by_family(sk->ss_family);
1663 if (!proto || !proto->connect) {
1664 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1665 file, linenum, args[0], args[1]);
1666 err_code |= ERR_ALERT | ERR_FATAL;
1667 goto out;
1668 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001669
1670 if (port1 != port2) {
1671 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1672 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
1674 goto out;
1675 }
1676
Willy Tarreau2aa38802013-02-20 19:20:59 +01001677 if (!port1) {
1678 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1679 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
1682 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001683
Emeric Brun32da3c42010-09-23 18:39:19 +02001684 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001685 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001686 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001687 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001688
Emeric Brun32da3c42010-09-23 18:39:19 +02001689 if (strcmp(newpeer->id, localpeer) == 0) {
1690 /* Current is local peer, it define a frontend */
1691 newpeer->local = 1;
1692
1693 if (!curpeers->peers_fe) {
1694 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1695 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1696 err_code |= ERR_ALERT | ERR_ABORT;
1697 goto out;
1698 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001699
Willy Tarreau237250c2011-07-29 01:49:03 +02001700 init_new_proxy(curpeers->peers_fe);
1701 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001702
1703 curpeers->peers_fe->last_change = now.tv_sec;
1704 curpeers->peers_fe->id = strdup(args[1]);
1705 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001706 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001707 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1708 curpeers->peers_fe->timeout.connect = 5000;
1709 curpeers->peers_fe->accept = peer_accept;
1710 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001711 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1712 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001713
1714 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1715
Willy Tarreau902636f2013-03-10 19:44:48 +01001716 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1717 if (errmsg && *errmsg) {
1718 indent_msg(&errmsg, 2);
1719 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001720 }
1721 else
1722 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1723 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001724 err_code |= ERR_FATAL;
1725 goto out;
1726 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001727
1728 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1729 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1730 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1731 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1732 l->accept = session_accept;
1733 l->handler = process_session;
1734 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1735 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1736 global.maxsock += l->maxconn;
1737 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001738 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001739 else {
1740 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1741 file, linenum, args[0], args[1],
1742 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1743 err_code |= ERR_FATAL;
1744 goto out;
1745 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001746 }
1747 } /* neither "peer" nor "peers" */
1748 else if (*args[0] != 0) {
1749 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
1752 }
1753
1754out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001755 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001756 return err_code;
1757}
1758
Willy Tarreau3842f002009-06-14 11:39:52 +02001759int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760{
1761 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001762 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001763 int rc;
1764 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001765 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001766 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001767 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001768 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001769 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreau977b8e42006-12-29 14:19:17 +01001771 if (!strcmp(args[0], "listen"))
1772 rc = PR_CAP_LISTEN;
1773 else if (!strcmp(args[0], "frontend"))
1774 rc = PR_CAP_FE | PR_CAP_RS;
1775 else if (!strcmp(args[0], "backend"))
1776 rc = PR_CAP_BE | PR_CAP_RS;
1777 else if (!strcmp(args[0], "ruleset"))
1778 rc = PR_CAP_RS;
1779 else
1780 rc = PR_CAP_NONE;
1781
1782 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001783 struct ebpt_node *node;
1784
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785 if (!*args[1]) {
1786 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1787 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1788 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_ALERT | ERR_ABORT;
1790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001792
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001793 err = invalid_char(args[1]);
1794 if (err) {
1795 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1796 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001797 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001798 }
1799
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001800 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1801 curproxy = container_of(node, struct proxy, conf.by_name);
1802
1803 if (strcmp(curproxy->id, args[1]) != 0)
1804 break;
1805
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001806 /*
1807 * If there are two proxies with the same name only following
1808 * combinations are allowed:
1809 *
1810 * listen backend frontend ruleset
1811 * listen - - - -
1812 * backend - - OK -
1813 * frontend - OK - -
1814 * ruleset - - - -
1815 */
1816
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001817 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1818 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001819 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1820 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1821 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001822 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001823 }
1824 }
1825
Willy Tarreaubaaee002006-06-26 02:48:02 +02001826 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1827 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001828 err_code |= ERR_ALERT | ERR_ABORT;
1829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001831
Willy Tarreau97cb7802010-01-03 20:23:58 +01001832 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833 curproxy->next = proxy;
1834 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001835 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1836 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001837 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001838 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001839 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001840 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001841
1842 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001843 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001844 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001845
Willy Tarreau4348fad2012-09-20 16:48:07 +02001846 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1847
Willy Tarreau902636f2013-03-10 19:44:48 +01001848 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1849 if (errmsg && *errmsg) {
1850 indent_msg(&errmsg, 2);
1851 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001852 }
1853 else
1854 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1855 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_FATAL;
1857 goto out;
1858 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001859
Willy Tarreau4348fad2012-09-20 16:48:07 +02001860 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001861 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863 }
1864
1865 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001866 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001867 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001868
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001871 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001872 curproxy->no_options = defproxy.no_options;
1873 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001874 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001875 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001876 curproxy->except_net = defproxy.except_net;
1877 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001878 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001879 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001881 if (defproxy.fwdfor_hdr_len) {
1882 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1883 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1884 }
1885
Willy Tarreaub86db342009-11-30 11:50:16 +01001886 if (defproxy.orgto_hdr_len) {
1887 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1888 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1889 }
1890
Mark Lamourinec2247f02012-01-04 13:02:01 -05001891 if (defproxy.server_id_hdr_len) {
1892 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1893 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1894 }
1895
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 if (curproxy->cap & PR_CAP_FE) {
1897 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001898 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001899 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900
1901 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001902 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1903 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904
1905 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907
Willy Tarreau977b8e42006-12-29 14:19:17 +01001908 if (curproxy->cap & PR_CAP_BE) {
1909 curproxy->fullconn = defproxy.fullconn;
1910 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001912 if (defproxy.check_req) {
1913 curproxy->check_req = calloc(1, defproxy.check_len);
1914 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1915 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001918 if (defproxy.expect_str) {
1919 curproxy->expect_str = strdup(defproxy.expect_str);
1920 if (defproxy.expect_regex) {
1921 /* note: this regex is known to be valid */
1922 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1923 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1924 }
1925 }
1926
Willy Tarreau67402132012-05-31 20:40:20 +02001927 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 if (defproxy.cookie_name)
1929 curproxy->cookie_name = strdup(defproxy.cookie_name);
1930 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001931 if (defproxy.cookie_domain)
1932 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001933
Willy Tarreau31936852010-10-06 16:59:56 +02001934 if (defproxy.cookie_maxidle)
1935 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1936
1937 if (defproxy.cookie_maxlife)
1938 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1939
Emeric Brun647caf12009-06-30 17:57:00 +02001940 if (defproxy.rdp_cookie_name)
1941 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1942 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1943
Willy Tarreau01732802007-11-01 22:48:15 +01001944 if (defproxy.url_param_name)
1945 curproxy->url_param_name = strdup(defproxy.url_param_name);
1946 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001947
Benoitaffb4812009-03-25 13:02:10 +01001948 if (defproxy.hh_name)
1949 curproxy->hh_name = strdup(defproxy.hh_name);
1950 curproxy->hh_len = defproxy.hh_len;
1951 curproxy->hh_match_domain = defproxy.hh_match_domain;
1952
Willy Tarreauef9a3602012-12-08 22:29:20 +01001953 if (defproxy.conn_src.iface_name)
1954 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1955 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001956 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001957#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001958 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001959#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001962 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001963 if (defproxy.capture_name)
1964 curproxy->capture_name = strdup(defproxy.capture_name);
1965 curproxy->capture_namelen = defproxy.capture_namelen;
1966 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001970 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001971 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001972 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001973 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001974 curproxy->mon_net = defproxy.mon_net;
1975 curproxy->mon_mask = defproxy.mon_mask;
1976 if (defproxy.monitor_uri)
1977 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1978 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001979 if (defproxy.defbe.name)
1980 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001981
1982 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001983 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1984 if (curproxy->conf.logformat_string &&
1985 curproxy->conf.logformat_string != default_http_log_format &&
1986 curproxy->conf.logformat_string != default_tcp_log_format &&
1987 curproxy->conf.logformat_string != clf_http_log_format)
1988 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1989
1990 if (defproxy.conf.lfs_file) {
1991 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1992 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001994 }
1995
1996 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001997 curproxy->timeout.connect = defproxy.timeout.connect;
1998 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001999 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002000 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002001 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002002 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002003 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002004 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002005 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002006 }
2007
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002009 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002010
2011 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002012 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002013 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002014 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002015 LIST_INIT(&node->list);
2016 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2017 }
2018
Willy Tarreau62a61232013-04-12 18:13:46 +02002019 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2020 if (curproxy->conf.uniqueid_format_string)
2021 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2022
2023 if (defproxy.conf.uif_file) {
2024 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2025 curproxy->conf.uif_line = defproxy.conf.uif_line;
2026 }
William Lallemanda73203e2012-03-12 12:48:57 +01002027
2028 /* copy default header unique id */
2029 if (defproxy.header_unique_id)
2030 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2031
William Lallemand82fe75c2012-10-23 10:25:10 +02002032 /* default compression options */
2033 if (defproxy.comp != NULL) {
2034 curproxy->comp = calloc(1, sizeof(struct comp));
2035 curproxy->comp->algos = defproxy.comp->algos;
2036 curproxy->comp->types = defproxy.comp->types;
2037 }
2038
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002040 curproxy->conf.used_listener_id = EB_ROOT;
2041 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002042
Willy Tarreau93893792009-07-23 13:19:11 +02002043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 }
2045 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2046 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002047 /* FIXME-20070101: we should do this too at the end of the
2048 * config parsing to free all default values.
2049 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002050 free(defproxy.check_req);
2051 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002052 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002053 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002054 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002055 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002056 free(defproxy.capture_name);
2057 free(defproxy.monitor_uri);
2058 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002059 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002060 free(defproxy.fwdfor_hdr_name);
2061 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002062 free(defproxy.orgto_hdr_name);
2063 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002064 free(defproxy.server_id_hdr_name);
2065 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002066 free(defproxy.expect_str);
2067 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002068
Willy Tarreau62a61232013-04-12 18:13:46 +02002069 if (defproxy.conf.logformat_string != default_http_log_format &&
2070 defproxy.conf.logformat_string != default_tcp_log_format &&
2071 defproxy.conf.logformat_string != clf_http_log_format)
2072 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002073
Willy Tarreau62a61232013-04-12 18:13:46 +02002074 free(defproxy.conf.uniqueid_format_string);
2075 free(defproxy.conf.lfs_file);
2076 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002077
Willy Tarreaua534fea2008-08-03 12:19:50 +02002078 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002079 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002080
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 /* we cannot free uri_auth because it might already be used */
2082 init_default_instance();
2083 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002084 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2085 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 }
2089 else if (curproxy == NULL) {
2090 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002094
2095 /* update the current file and line being parsed */
2096 curproxy->conf.args.file = curproxy->conf.file;
2097 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002098
2099 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002100 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2101 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2102 if (err_code & ERR_FATAL)
2103 goto out;
2104 }
2105 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002106 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002107 int cur_arg;
2108
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 if (curproxy == &defproxy) {
2110 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002111 err_code |= ERR_ALERT | ERR_FATAL;
2112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002114 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116
Willy Tarreau24709282013-03-10 21:32:12 +01002117 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002118 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002123
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002124 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002125
2126 /* use default settings for unix sockets */
2127 bind_conf->ux.uid = global.unix_bind.ux.uid;
2128 bind_conf->ux.gid = global.unix_bind.ux.gid;
2129 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002130
2131 /* NOTE: the following line might create several listeners if there
2132 * are comma-separated IPs or port ranges. So all further processing
2133 * will have to be applied to all listeners created after last_listen.
2134 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002135 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2136 if (errmsg && *errmsg) {
2137 indent_msg(&errmsg, 2);
2138 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002139 }
2140 else
2141 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2142 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
2145 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002146
Willy Tarreau4348fad2012-09-20 16:48:07 +02002147 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2148 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002149 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002150 }
2151
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002152 cur_arg = 2;
2153 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002154 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002155 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002156 char *err;
2157
Willy Tarreau26982662012-09-12 23:17:10 +02002158 kw = bind_find_kw(args[cur_arg]);
2159 if (kw) {
2160 char *err = NULL;
2161 int code;
2162
2163 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002164 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2165 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002166 cur_arg += 1 + kw->skip ;
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
Willy Tarreau4348fad2012-09-20 16:48:07 +02002171 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002172 err_code |= code;
2173
2174 if (code) {
2175 if (err && *err) {
2176 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002177 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002178 }
2179 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002180 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2181 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002182 if (code & ERR_FATAL) {
2183 free(err);
2184 cur_arg += 1 + kw->skip;
2185 goto out;
2186 }
2187 }
2188 free(err);
2189 cur_arg += 1 + kw->skip;
2190 continue;
2191 }
2192
Willy Tarreau8638f482012-09-18 18:01:17 +02002193 err = NULL;
2194 if (!bind_dumped) {
2195 bind_dump_kws(&err);
2196 indent_msg(&err, 4);
2197 bind_dumped = 1;
2198 }
2199
2200 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2201 file, linenum, args[0], args[1], args[cur_arg],
2202 err ? " Registered keywords :" : "", err ? err : "");
2203 free(err);
2204
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002207 }
Willy Tarreau93893792009-07-23 13:19:11 +02002208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }
2210 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002211 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002219
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 /* flush useless bits */
2221 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002223 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002224 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227
Willy Tarreau1c47f852006-07-09 08:22:27 +02002228 if (!*args[1]) {
2229 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2230 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002233 }
2234
Willy Tarreaua534fea2008-08-03 12:19:50 +02002235 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002236 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002237 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002238 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002239 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2240
Willy Tarreau93893792009-07-23 13:19:11 +02002241 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2244 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2245 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2246 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2247 else {
2248 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
2252 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002253 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002254 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002255
2256 if (curproxy == &defproxy) {
2257 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2258 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002261 }
2262
2263 if (!*args[1]) {
2264 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2265 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002268 }
2269
2270 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002271 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002272
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002273 if (curproxy->uuid <= 0) {
2274 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002275 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002276 err_code |= ERR_ALERT | ERR_FATAL;
2277 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002278 }
2279
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002280 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2281 if (node) {
2282 struct proxy *target = container_of(node, struct proxy, conf.id);
2283 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2284 file, linenum, proxy_type_str(curproxy), curproxy->id,
2285 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002290 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002291 else if (!strcmp(args[0], "description")) {
2292 int i, len=0;
2293 char *d;
2294
Cyril Bonté99ed3272010-01-24 23:29:44 +01002295 if (curproxy == &defproxy) {
2296 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2297 file, linenum, args[0]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002302 if (!*args[1]) {
2303 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2304 file, linenum, args[0]);
2305 return -1;
2306 }
2307
Willy Tarreau348acfe2014-04-14 15:00:39 +02002308 for (i = 1; *args[i]; i++)
2309 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002310
2311 d = (char *)calloc(1, len);
2312 curproxy->desc = d;
2313
Willy Tarreau348acfe2014-04-14 15:00:39 +02002314 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2315 for (i = 2; *args[i]; i++)
2316 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002317
2318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2320 curproxy->state = PR_STSTOPPED;
2321 }
2322 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2323 curproxy->state = PR_STNEW;
2324 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002325 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2326 int cur_arg = 1;
2327 unsigned int set = 0;
2328
2329 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002330 unsigned int low, high;
2331
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002332 if (strcmp(args[cur_arg], "all") == 0) {
2333 set = 0;
2334 break;
2335 }
2336 else if (strcmp(args[cur_arg], "odd") == 0) {
2337 set |= 0x55555555;
2338 }
2339 else if (strcmp(args[cur_arg], "even") == 0) {
2340 set |= 0xAAAAAAAA;
2341 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002342 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002343 char *dash = strchr(args[cur_arg], '-');
2344
2345 low = high = str2uic(args[cur_arg]);
2346 if (dash)
2347 high = str2uic(dash + 1);
2348
2349 if (high < low) {
2350 unsigned int swap = low;
2351 low = high;
2352 high = swap;
2353 }
2354
2355 if (low < 1 || high > 32) {
2356 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002357 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002360 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002361
2362 if (high > global.nbproc) {
2363 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2364 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002366 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002367 while (low <= high)
2368 set |= 1 << (low++ - 1);
2369 }
2370 else {
2371 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2372 file, linenum, args[0]);
2373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002375 }
2376 cur_arg++;
2377 }
2378 curproxy->bind_proc = set;
2379 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002380 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002381 if (curproxy == &defproxy) {
2382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002385 }
2386
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002387 err = invalid_char(args[1]);
2388 if (err) {
2389 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2390 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002392 }
2393
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002394 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002395 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2396 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002399 }
2400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2402 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 if (*(args[1]) == 0) {
2408 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2409 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002413
Willy Tarreau67402132012-05-31 20:40:20 +02002414 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002415 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002416 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002417 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 curproxy->cookie_name = strdup(args[1]);
2419 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002420
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 cur_arg = 2;
2422 while (*(args[cur_arg])) {
2423 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002424 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 }
2426 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002427 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
2429 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002430 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
2432 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002433 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
2435 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002436 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002438 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002439 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002442 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002444 else if (!strcmp(args[cur_arg], "httponly")) {
2445 curproxy->ck_opts |= PR_CK_HTTPONLY;
2446 }
2447 else if (!strcmp(args[cur_arg], "secure")) {
2448 curproxy->ck_opts |= PR_CK_SECURE;
2449 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002450 else if (!strcmp(args[cur_arg], "domain")) {
2451 if (!*args[cur_arg + 1]) {
2452 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2453 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002456 }
2457
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002458 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002459 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002460 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2461 " dots nor does not start with a dot."
2462 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002463 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002464 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002465 }
2466
2467 err = invalid_domainchar(args[cur_arg + 1]);
2468 if (err) {
2469 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2470 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002473 }
2474
Willy Tarreau68a897b2009-12-03 23:28:34 +01002475 if (!curproxy->cookie_domain) {
2476 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2477 } else {
2478 /* one domain was already specified, add another one by
2479 * building the string which will be returned along with
2480 * the cookie.
2481 */
2482 char *new_ptr;
2483 int new_len = strlen(curproxy->cookie_domain) +
2484 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2485 new_ptr = malloc(new_len);
2486 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2487 free(curproxy->cookie_domain);
2488 curproxy->cookie_domain = new_ptr;
2489 }
Willy Tarreau31936852010-10-06 16:59:56 +02002490 cur_arg++;
2491 }
2492 else if (!strcmp(args[cur_arg], "maxidle")) {
2493 unsigned int maxidle;
2494 const char *res;
2495
2496 if (!*args[cur_arg + 1]) {
2497 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2498 file, linenum, args[cur_arg]);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502
2503 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2504 if (res) {
2505 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2506 file, linenum, *res, args[cur_arg]);
2507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
2509 }
2510 curproxy->cookie_maxidle = maxidle;
2511 cur_arg++;
2512 }
2513 else if (!strcmp(args[cur_arg], "maxlife")) {
2514 unsigned int maxlife;
2515 const char *res;
2516
2517 if (!*args[cur_arg + 1]) {
2518 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2519 file, linenum, args[cur_arg]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523
2524 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2525 if (res) {
2526 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2527 file, linenum, *res, args[cur_arg]);
2528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
2530 }
2531 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002532 cur_arg++;
2533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002535 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 +02002536 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 }
2540 cur_arg++;
2541 }
Willy Tarreau67402132012-05-31 20:40:20 +02002542 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2544 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 }
2547
Willy Tarreau67402132012-05-31 20:40:20 +02002548 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2550 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002553
Willy Tarreau67402132012-05-31 20:40:20 +02002554 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002555 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2556 file, linenum);
2557 err_code |= ERR_ALERT | ERR_FATAL;
2558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002560 else if (!strcmp(args[0], "persist")) { /* persist */
2561 if (*(args[1]) == 0) {
2562 Alert("parsing [%s:%d] : missing persist method.\n",
2563 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002566 }
2567
2568 if (!strncmp(args[1], "rdp-cookie", 10)) {
2569 curproxy->options2 |= PR_O2_RDPC_PRST;
2570
Emeric Brunb982a3d2010-01-04 15:45:53 +01002571 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002572 const char *beg, *end;
2573
2574 beg = args[1] + 11;
2575 end = strchr(beg, ')');
2576
2577 if (!end || end == beg) {
2578 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2579 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002582 }
2583
2584 free(curproxy->rdp_cookie_name);
2585 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2586 curproxy->rdp_cookie_len = end-beg;
2587 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002588 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002589 free(curproxy->rdp_cookie_name);
2590 curproxy->rdp_cookie_name = strdup("msts");
2591 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2592 }
2593 else { /* syntax */
2594 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2595 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002598 }
2599 }
2600 else {
2601 Alert("parsing [%s:%d] : unknown persist method.\n",
2602 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002605 }
2606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002608 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002610 if (curproxy == &defproxy) {
2611 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
2614 }
2615
Willy Tarreau977b8e42006-12-29 14:19:17 +01002616 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002618
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002620 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 }
2625 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002626 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 curproxy->appsession_name = strdup(args[1]);
2628 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2629 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002630 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2631 if (err) {
2632 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2633 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002636 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002637 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002638
Willy Tarreau51041c72007-09-09 21:56:53 +02002639 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2640 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_ABORT;
2642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002644
2645 cur_arg = 6;
2646 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002647 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2648 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002649 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002650 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002651 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002652 } else if (!strcmp(args[cur_arg], "prefix")) {
2653 curproxy->options2 |= PR_O2_AS_PFX;
2654 } else if (!strcmp(args[cur_arg], "mode")) {
2655 if (!*args[cur_arg + 1]) {
2656 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2657 file, linenum, args[0], args[cur_arg]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661
2662 cur_arg++;
2663 if (!strcmp(args[cur_arg], "query-string")) {
2664 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2665 curproxy->options2 |= PR_O2_AS_M_QS;
2666 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2667 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2668 curproxy->options2 |= PR_O2_AS_M_PP;
2669 } else {
2670 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002675 cur_arg++;
2676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 } /* Url App Session */
2678 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002679 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002681
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002683 if (curproxy == &defproxy) {
2684 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 if (*(args[4]) == 0) {
2690 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2691 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002695 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 curproxy->capture_name = strdup(args[2]);
2697 curproxy->capture_namelen = strlen(curproxy->capture_name);
2698 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 curproxy->to_log |= LW_COOKIE;
2700 }
2701 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2702 struct cap_hdr *hdr;
2703
2704 if (curproxy == &defproxy) {
2705 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 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 }
2709
2710 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2711 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2712 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 }
2716
2717 hdr = calloc(sizeof(struct cap_hdr), 1);
2718 hdr->next = curproxy->req_cap;
2719 hdr->name = strdup(args[3]);
2720 hdr->namelen = strlen(args[3]);
2721 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002722 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 hdr->index = curproxy->nb_req_cap++;
2724 curproxy->req_cap = hdr;
2725 curproxy->to_log |= LW_REQHDR;
2726 }
2727 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2728 struct cap_hdr *hdr;
2729
2730 if (curproxy == &defproxy) {
2731 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 }
2735
2736 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2737 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2738 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741 }
2742 hdr = calloc(sizeof(struct cap_hdr), 1);
2743 hdr->next = curproxy->rsp_cap;
2744 hdr->name = strdup(args[3]);
2745 hdr->namelen = strlen(args[3]);
2746 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002747 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 hdr->index = curproxy->nb_rsp_cap++;
2749 curproxy->rsp_cap = hdr;
2750 curproxy->to_log |= LW_RSPHDR;
2751 }
2752 else {
2753 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2754 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 }
2758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 if (*(args[1]) == 0) {
2764 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2765 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 }
2769 curproxy->conn_retries = atol(args[1]);
2770 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002771 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002772 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002773
2774 if (curproxy == &defproxy) {
2775 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
2778 }
2779
Willy Tarreau20b0de52012-12-24 15:45:22 +01002780 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2781 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2782 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2783 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002784 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002785 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2786 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 +01002787 file, linenum, args[0]);
2788 err_code |= ERR_WARN;
2789 }
2790
Willy Tarreauff011f22011-01-06 17:51:27 +01002791 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002792
Willy Tarreauff011f22011-01-06 17:51:27 +01002793 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002794 err_code |= ERR_ALERT | ERR_ABORT;
2795 goto out;
2796 }
2797
Willy Tarreau5002f572014-04-23 01:32:02 +02002798 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002799 err_code |= warnif_cond_conflicts(rule->cond,
2800 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2801 file, linenum);
2802
Willy Tarreauff011f22011-01-06 17:51:27 +01002803 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002804 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002805 else if (!strcmp(args[0], "http-response")) { /* response access control */
2806 struct http_res_rule *rule;
2807
2808 if (curproxy == &defproxy) {
2809 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
2812 }
2813
2814 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2815 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2816 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2817 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2818 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2819 file, linenum, args[0]);
2820 err_code |= ERR_WARN;
2821 }
2822
2823 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2824
2825 if (!rule) {
2826 err_code |= ERR_ALERT | ERR_ABORT;
2827 goto out;
2828 }
2829
2830 err_code |= warnif_cond_conflicts(rule->cond,
2831 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2832 file, linenum);
2833
2834 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2835 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002836 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2837 /* set the header name and length into the proxy structure */
2838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2839 err_code |= ERR_WARN;
2840
2841 if (!*args[1]) {
2842 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2843 file, linenum, args[0]);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846 }
2847
2848 /* set the desired header name */
2849 free(curproxy->server_id_hdr_name);
2850 curproxy->server_id_hdr_name = strdup(args[1]);
2851 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2852 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002853 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002854 if (curproxy == &defproxy) {
2855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002858 }
2859
Willy Tarreauef6494c2010-01-28 17:12:36 +01002860 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002861 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2862 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002865 }
2866
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002867 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2868 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2869 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002872 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002873
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002874 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002875 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002876 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002877 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002878 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002879
Cyril Bonté99ed3272010-01-24 23:29:44 +01002880 if (curproxy == &defproxy) {
2881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
2884 }
2885
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002886 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002887 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2888 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002891 }
2892
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002893 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002894 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002895 err_code |= warnif_cond_conflicts(rule->cond,
2896 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2897 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002898 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002899 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002900 struct switching_rule *rule;
2901
Willy Tarreaub099aca2008-10-12 17:26:37 +02002902 if (curproxy == &defproxy) {
2903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002906 }
2907
Willy Tarreau55ea7572007-06-17 19:56:27 +02002908 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002910
2911 if (*(args[1]) == 0) {
2912 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002915 }
2916
Willy Tarreauf51658d2014-04-23 01:21:56 +02002917 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2918 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2919 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2920 file, linenum, errmsg);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002924
Willy Tarreauf51658d2014-04-23 01:21:56 +02002925 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002926 }
2927
2928 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2929 rule->cond = cond;
2930 rule->be.name = strdup(args[1]);
2931 LIST_INIT(&rule->list);
2932 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2933 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002934 else if (strcmp(args[0], "use-server") == 0) {
2935 struct server_rule *rule;
2936
2937 if (curproxy == &defproxy) {
2938 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
2942
2943 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2944 err_code |= ERR_WARN;
2945
2946 if (*(args[1]) == 0) {
2947 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951
2952 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2953 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2954 file, linenum, args[0]);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002959 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2960 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2961 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002966 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002967
2968 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2969 rule->cond = cond;
2970 rule->srv.name = strdup(args[1]);
2971 LIST_INIT(&rule->list);
2972 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2973 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2974 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002975 else if ((!strcmp(args[0], "force-persist")) ||
2976 (!strcmp(args[0], "ignore-persist"))) {
2977 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002978
2979 if (curproxy == &defproxy) {
2980 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
2984
2985 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2986 err_code |= ERR_WARN;
2987
Willy Tarreauef6494c2010-01-28 17:12:36 +01002988 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002989 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2990 file, linenum, args[0]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002995 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2996 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2997 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
3000 }
3001
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003002 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3003 * where force-persist is applied.
3004 */
3005 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003006
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003007 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003008 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003009 if (!strcmp(args[0], "force-persist")) {
3010 rule->type = PERSIST_TYPE_FORCE;
3011 } else {
3012 rule->type = PERSIST_TYPE_IGNORE;
3013 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003014 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003015 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003016 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003017 else if (!strcmp(args[0], "stick-table")) {
3018 int myidx = 1;
3019
Emeric Brun32da3c42010-09-23 18:39:19 +02003020 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003021 curproxy->table.type = (unsigned int)-1;
3022 while (*args[myidx]) {
3023 const char *err;
3024
3025 if (strcmp(args[myidx], "size") == 0) {
3026 myidx++;
3027 if (!*(args[myidx])) {
3028 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3029 file, linenum, args[myidx-1]);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
3033 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3034 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3035 file, linenum, *err, args[myidx-1]);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003039 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003041 else if (strcmp(args[myidx], "peers") == 0) {
3042 myidx++;
Godbach50523162013-12-11 19:48:57 +08003043 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003044 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3045 file, linenum, args[myidx-1]);
3046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Godbach50523162013-12-11 19:48:57 +08003048 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003049 curproxy->table.peers.name = strdup(args[myidx++]);
3050 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003051 else if (strcmp(args[myidx], "expire") == 0) {
3052 myidx++;
3053 if (!*(args[myidx])) {
3054 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3055 file, linenum, args[myidx-1]);
3056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
3058 }
3059 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3060 if (err) {
3061 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3062 file, linenum, *err, args[myidx-1]);
3063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
3065 }
3066 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003067 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 }
3069 else if (strcmp(args[myidx], "nopurge") == 0) {
3070 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003071 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003072 }
3073 else if (strcmp(args[myidx], "type") == 0) {
3074 myidx++;
3075 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3076 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3077 file, linenum, args[myidx]);
3078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
3080 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003081 /* myidx already points to next arg */
3082 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003083 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003084 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003085 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003086
3087 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003088 nw = args[myidx];
3089 while (*nw) {
3090 /* the "store" keyword supports a comma-separated list */
3091 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003092 sa = NULL; /* store arg */
3093 while (*nw && *nw != ',') {
3094 if (*nw == '(') {
3095 *nw = 0;
3096 sa = ++nw;
3097 while (*nw != ')') {
3098 if (!*nw) {
3099 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3100 file, linenum, args[0], cw);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104 nw++;
3105 }
3106 *nw = '\0';
3107 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003108 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003109 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003110 if (*nw)
3111 *nw++ = '\0';
3112 type = stktable_get_data_type(cw);
3113 if (type < 0) {
3114 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3115 file, linenum, args[0], cw);
3116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
Willy Tarreauac782882010-06-20 10:41:54 +02003119
3120 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3121 switch (err) {
3122 case PE_NONE: break;
3123 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003124 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3125 file, linenum, args[0], cw);
3126 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003127 break;
3128
3129 case PE_ARG_MISSING:
3130 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3131 file, linenum, args[0], cw);
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
3134
3135 case PE_ARG_NOT_USED:
3136 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3137 file, linenum, args[0], cw);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
3140
3141 default:
3142 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3143 file, linenum, args[0], cw);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003146 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003147 }
3148 myidx++;
3149 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003150 else {
3151 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3152 file, linenum, args[myidx]);
3153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003155 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003156 }
3157
3158 if (!curproxy->table.size) {
3159 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3160 file, linenum);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164
3165 if (curproxy->table.type == (unsigned int)-1) {
3166 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3167 file, linenum);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171 }
3172 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003173 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003174 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003175 int myidx = 0;
3176 const char *name = NULL;
3177 int flags;
3178
3179 if (curproxy == &defproxy) {
3180 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
3183 }
3184
3185 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3186 err_code |= ERR_WARN;
3187 goto out;
3188 }
3189
3190 myidx++;
3191 if ((strcmp(args[myidx], "store") == 0) ||
3192 (strcmp(args[myidx], "store-request") == 0)) {
3193 myidx++;
3194 flags = STK_IS_STORE;
3195 }
3196 else if (strcmp(args[myidx], "store-response") == 0) {
3197 myidx++;
3198 flags = STK_IS_STORE | STK_ON_RSP;
3199 }
3200 else if (strcmp(args[myidx], "match") == 0) {
3201 myidx++;
3202 flags = STK_IS_MATCH;
3203 }
3204 else if (strcmp(args[myidx], "on") == 0) {
3205 myidx++;
3206 flags = STK_IS_MATCH | STK_IS_STORE;
3207 }
3208 else {
3209 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213
3214 if (*(args[myidx]) == 0) {
3215 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
3219
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003220 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003221 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003223 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
3227
3228 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003229 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3230 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3231 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003232 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003233 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003234 goto out;
3235 }
3236 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003237 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3238 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3239 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003240 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003241 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003242 goto out;
3243 }
3244 }
3245
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003246 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003247 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003248
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 if (strcmp(args[myidx], "table") == 0) {
3250 myidx++;
3251 name = args[myidx++];
3252 }
3253
Willy Tarreauef6494c2010-01-28 17:12:36 +01003254 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003255 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3256 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3257 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003258 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003259 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003260 goto out;
3261 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003262 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003263 else if (*(args[myidx])) {
3264 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3265 file, linenum, args[0], args[myidx]);
3266 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003267 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003268 goto out;
3269 }
Emeric Brun97679e72010-09-23 17:56:44 +02003270 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003271 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003272 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003273 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003274
Emeric Brunb982a3d2010-01-04 15:45:53 +01003275 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3276 rule->cond = cond;
3277 rule->expr = expr;
3278 rule->flags = flags;
3279 rule->table.name = name ? strdup(name) : NULL;
3280 LIST_INIT(&rule->list);
3281 if (flags & STK_ON_RSP)
3282 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3283 else
3284 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 else if (!strcmp(args[0], "stats")) {
3287 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3288 curproxy->uri_auth = NULL; /* we must detach from the default config */
3289
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003290 if (!*args[1]) {
3291 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003292 } else if (!strcmp(args[1], "admin")) {
3293 struct stats_admin_rule *rule;
3294
3295 if (curproxy == &defproxy) {
3296 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
3299 }
3300
3301 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3302 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3303 err_code |= ERR_ALERT | ERR_ABORT;
3304 goto out;
3305 }
3306
3307 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3308 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3309 file, linenum, args[0], args[1]);
3310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
3312 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003313 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3314 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3315 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
3318 }
3319
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003320 err_code |= warnif_cond_conflicts(cond,
3321 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3322 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003323
3324 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3325 rule->cond = cond;
3326 LIST_INIT(&rule->list);
3327 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 } else if (!strcmp(args[1], "uri")) {
3329 if (*(args[2]) == 0) {
3330 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3334 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_ABORT;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
3338 } else if (!strcmp(args[1], "realm")) {
3339 if (*(args[2]) == 0) {
3340 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3344 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_ABORT;
3346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003348 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003349 unsigned interval;
3350
3351 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3352 if (err) {
3353 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3354 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003357 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3358 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_ABORT;
3360 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003361 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003362 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003363 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003364
3365 if (curproxy == &defproxy) {
3366 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
3369 }
3370
3371 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3372 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3373 err_code |= ERR_ALERT | ERR_ABORT;
3374 goto out;
3375 }
3376
Willy Tarreauff011f22011-01-06 17:51:27 +01003377 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3378 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003379 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3380 file, linenum, args[0]);
3381 err_code |= ERR_WARN;
3382 }
3383
Willy Tarreauff011f22011-01-06 17:51:27 +01003384 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003385
Willy Tarreauff011f22011-01-06 17:51:27 +01003386 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003387 err_code |= ERR_ALERT | ERR_ABORT;
3388 goto out;
3389 }
3390
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003391 err_code |= warnif_cond_conflicts(rule->cond,
3392 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3393 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003394 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003395
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 } else if (!strcmp(args[1], "auth")) {
3397 if (*(args[2]) == 0) {
3398 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3402 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_ABORT;
3404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406 } else if (!strcmp(args[1], "scope")) {
3407 if (*(args[2]) == 0) {
3408 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3412 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_ALERT | ERR_ABORT;
3414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 }
3416 } else if (!strcmp(args[1], "enable")) {
3417 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3418 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_ABORT;
3420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003422 } else if (!strcmp(args[1], "hide-version")) {
3423 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3424 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003425 err_code |= ERR_ALERT | ERR_ABORT;
3426 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003427 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003428 } else if (!strcmp(args[1], "show-legends")) {
3429 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3430 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3431 err_code |= ERR_ALERT | ERR_ABORT;
3432 goto out;
3433 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003434 } else if (!strcmp(args[1], "show-node")) {
3435
3436 if (*args[2]) {
3437 int i;
3438 char c;
3439
3440 for (i=0; args[2][i]; i++) {
3441 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003442 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3443 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003444 break;
3445 }
3446
3447 if (!i || args[2][i]) {
3448 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3449 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3450 file, linenum, args[0], args[1]);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454 }
3455
3456 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3457 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3458 err_code |= ERR_ALERT | ERR_ABORT;
3459 goto out;
3460 }
3461 } else if (!strcmp(args[1], "show-desc")) {
3462 char *desc = NULL;
3463
3464 if (*args[2]) {
3465 int i, len=0;
3466 char *d;
3467
Willy Tarreau348acfe2014-04-14 15:00:39 +02003468 for (i = 2; *args[i]; i++)
3469 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003470
3471 desc = d = (char *)calloc(1, len);
3472
Willy Tarreau348acfe2014-04-14 15:00:39 +02003473 d += snprintf(d, desc + len - d, "%s", args[2]);
3474 for (i = 3; *args[i]; i++)
3475 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003476 }
3477
3478 if (!*args[2] && !global.desc)
3479 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3480 file, linenum, args[1]);
3481 else {
3482 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3483 free(desc);
3484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3485 err_code |= ERR_ALERT | ERR_ABORT;
3486 goto out;
3487 }
3488 free(desc);
3489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003491stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003492 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 +01003493 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 }
3497 }
3498 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003499 int optnum;
3500
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003501 if (*(args[1]) == '\0') {
3502 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003507
3508 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3509 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003510 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3511 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3512 file, linenum, cfg_opts[optnum].name);
3513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
3515 }
Willy Tarreau93893792009-07-23 13:19:11 +02003516 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3517 err_code |= ERR_WARN;
3518 goto out;
3519 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003520
Willy Tarreau3842f002009-06-14 11:39:52 +02003521 curproxy->no_options &= ~cfg_opts[optnum].val;
3522 curproxy->options &= ~cfg_opts[optnum].val;
3523
3524 switch (kwm) {
3525 case KWM_STD:
3526 curproxy->options |= cfg_opts[optnum].val;
3527 break;
3528 case KWM_NO:
3529 curproxy->no_options |= cfg_opts[optnum].val;
3530 break;
3531 case KWM_DEF: /* already cleared */
3532 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003533 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003534
Willy Tarreau93893792009-07-23 13:19:11 +02003535 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003536 }
3537 }
3538
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003539 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3540 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003541 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3542 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3543 file, linenum, cfg_opts2[optnum].name);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
Willy Tarreau93893792009-07-23 13:19:11 +02003547 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3548 err_code |= ERR_WARN;
3549 goto out;
3550 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003551
Willy Tarreau3842f002009-06-14 11:39:52 +02003552 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3553 curproxy->options2 &= ~cfg_opts2[optnum].val;
3554
3555 switch (kwm) {
3556 case KWM_STD:
3557 curproxy->options2 |= cfg_opts2[optnum].val;
3558 break;
3559 case KWM_NO:
3560 curproxy->no_options2 |= cfg_opts2[optnum].val;
3561 break;
3562 case KWM_DEF: /* already cleared */
3563 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003564 }
Willy Tarreau93893792009-07-23 13:19:11 +02003565 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003566 }
3567 }
3568
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003569 /* HTTP options override each other. They can be cancelled using
3570 * "no option xxx" which only switches to default mode if the mode
3571 * was this one (useful for cancelling options set in defaults
3572 * sections).
3573 */
3574 if (strcmp(args[1], "httpclose") == 0) {
3575 if (kwm == KWM_STD) {
3576 curproxy->options &= ~PR_O_HTTP_MODE;
3577 curproxy->options |= PR_O_HTTP_PCL;
3578 goto out;
3579 }
3580 else if (kwm == KWM_NO) {
3581 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3582 curproxy->options &= ~PR_O_HTTP_MODE;
3583 goto out;
3584 }
3585 }
3586 else if (strcmp(args[1], "forceclose") == 0) {
3587 if (kwm == KWM_STD) {
3588 curproxy->options &= ~PR_O_HTTP_MODE;
3589 curproxy->options |= PR_O_HTTP_FCL;
3590 goto out;
3591 }
3592 else if (kwm == KWM_NO) {
3593 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3594 curproxy->options &= ~PR_O_HTTP_MODE;
3595 goto out;
3596 }
3597 }
3598 else if (strcmp(args[1], "http-server-close") == 0) {
3599 if (kwm == KWM_STD) {
3600 curproxy->options &= ~PR_O_HTTP_MODE;
3601 curproxy->options |= PR_O_HTTP_SCL;
3602 goto out;
3603 }
3604 else if (kwm == KWM_NO) {
3605 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3606 curproxy->options &= ~PR_O_HTTP_MODE;
3607 goto out;
3608 }
3609 }
3610 else if (strcmp(args[1], "http-keep-alive") == 0) {
3611 if (kwm == KWM_STD) {
3612 curproxy->options &= ~PR_O_HTTP_MODE;
3613 curproxy->options |= PR_O_HTTP_KAL;
3614 goto out;
3615 }
3616 else if (kwm == KWM_NO) {
3617 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3618 curproxy->options &= ~PR_O_HTTP_MODE;
3619 goto out;
3620 }
3621 }
3622 else if (strcmp(args[1], "http-tunnel") == 0) {
3623 if (kwm == KWM_STD) {
3624 curproxy->options &= ~PR_O_HTTP_MODE;
3625 curproxy->options |= PR_O_HTTP_TUN;
3626 goto out;
3627 }
3628 else if (kwm == KWM_NO) {
3629 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3630 curproxy->options &= ~PR_O_HTTP_MODE;
3631 goto out;
3632 }
3633 }
3634
Willy Tarreau3842f002009-06-14 11:39:52 +02003635 if (kwm != KWM_STD) {
3636 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003637 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003640 }
3641
Emeric Brun3a058f32009-06-30 18:26:00 +02003642 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003643 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003645 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003646 if (*(args[2]) != '\0') {
3647 if (!strcmp(args[2], "clf")) {
3648 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003649 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003650 } else {
3651 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003654 }
3655 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003656 if (curproxy->conf.logformat_string != default_http_log_format &&
3657 curproxy->conf.logformat_string != default_tcp_log_format &&
3658 curproxy->conf.logformat_string != clf_http_log_format)
3659 free(curproxy->conf.logformat_string);
3660 curproxy->conf.logformat_string = logformat;
3661
3662 free(curproxy->conf.lfs_file);
3663 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3664 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003665 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003666 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003668 if (curproxy->conf.logformat_string != default_http_log_format &&
3669 curproxy->conf.logformat_string != default_tcp_log_format &&
3670 curproxy->conf.logformat_string != clf_http_log_format)
3671 free(curproxy->conf.logformat_string);
3672 curproxy->conf.logformat_string = default_tcp_log_format;
3673
3674 free(curproxy->conf.lfs_file);
3675 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3676 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 else if (!strcmp(args[1], "tcpka")) {
3679 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003680 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003682
3683 if (curproxy->cap & PR_CAP_FE)
3684 curproxy->options |= PR_O_TCP_CLI_KA;
3685 if (curproxy->cap & PR_CAP_BE)
3686 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 }
3688 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003689 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003690 err_code |= ERR_WARN;
3691
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003693 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003694 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003695 curproxy->options2 &= ~PR_O2_CHK_ANY;
3696 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 if (!*args[2]) { /* no argument */
3698 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3699 curproxy->check_len = strlen(DEF_CHECK_REQ);
3700 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003701 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 curproxy->check_req = (char *)malloc(reqlen);
3703 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003704 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003706 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 if (*args[4])
3708 reqlen += strlen(args[4]);
3709 else
3710 reqlen += strlen("HTTP/1.0");
3711
3712 curproxy->check_req = (char *)malloc(reqlen);
3713 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003714 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003716 }
3717 else if (!strcmp(args[1], "ssl-hello-chk")) {
3718 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003721
Willy Tarreaua534fea2008-08-03 12:19:50 +02003722 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003723 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003724 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003725 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 }
Willy Tarreau23677902007-05-08 23:50:35 +02003727 else if (!strcmp(args[1], "smtpchk")) {
3728 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003729 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003730 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003731 curproxy->options2 &= ~PR_O2_CHK_ANY;
3732 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003733
3734 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3735 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3736 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3737 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3738 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3739 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3740 curproxy->check_req = (char *)malloc(reqlen);
3741 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3742 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3743 } else {
3744 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3745 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3746 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3747 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3748 }
3749 }
3750 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003751 else if (!strcmp(args[1], "pgsql-check")) {
3752 /* use PostgreSQL request to check servers' health */
3753 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3754 err_code |= ERR_WARN;
3755
3756 free(curproxy->check_req);
3757 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003758 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003759 curproxy->options2 |= PR_O2_PGSQL_CHK;
3760
3761 if (*(args[2])) {
3762 int cur_arg = 2;
3763
3764 while (*(args[cur_arg])) {
3765 if (strcmp(args[cur_arg], "user") == 0) {
3766 char * packet;
3767 uint32_t packet_len;
3768 uint32_t pv;
3769
3770 /* suboption header - needs additional argument for it */
3771 if (*(args[cur_arg+1]) == 0) {
3772 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3773 file, linenum, args[0], args[1], args[cur_arg]);
3774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
3776 }
3777
3778 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3779 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3780 pv = htonl(0x30000); /* protocol version 3.0 */
3781
3782 packet = (char*) calloc(1, packet_len);
3783
3784 memcpy(packet + 4, &pv, 4);
3785
3786 /* copy "user" */
3787 memcpy(packet + 8, "user", 4);
3788
3789 /* copy username */
3790 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3791
3792 free(curproxy->check_req);
3793 curproxy->check_req = packet;
3794 curproxy->check_len = packet_len;
3795
3796 packet_len = htonl(packet_len);
3797 memcpy(packet, &packet_len, 4);
3798 cur_arg += 2;
3799 } else {
3800 /* unknown suboption - catchall */
3801 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3802 file, linenum, args[0], args[1]);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806 } /* end while loop */
3807 }
3808 }
3809
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003810 else if (!strcmp(args[1], "redis-check")) {
3811 /* use REDIS PING request to check servers' health */
3812 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3813 err_code |= ERR_WARN;
3814
3815 free(curproxy->check_req);
3816 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003817 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003818 curproxy->options2 |= PR_O2_REDIS_CHK;
3819
3820 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3821 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3822 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3823 }
3824
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003825 else if (!strcmp(args[1], "mysql-check")) {
3826 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3828 err_code |= ERR_WARN;
3829
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003830 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003831 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003832 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003833 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003834
3835 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3836 * const char mysql40_client_auth_pkt[] = {
3837 * "\x0e\x00\x00" // packet length
3838 * "\x01" // packet number
3839 * "\x00\x00" // client capabilities
3840 * "\x00\x00\x01" // max packet
3841 * "haproxy\x00" // username (null terminated string)
3842 * "\x00" // filler (always 0x00)
3843 * "\x01\x00\x00" // packet length
3844 * "\x00" // packet number
3845 * "\x01" // COM_QUIT command
3846 * };
3847 */
3848
3849 if (*(args[2])) {
3850 int cur_arg = 2;
3851
3852 while (*(args[cur_arg])) {
3853 if (strcmp(args[cur_arg], "user") == 0) {
3854 char *mysqluser;
3855 int packetlen, reqlen, userlen;
3856
3857 /* suboption header - needs additional argument for it */
3858 if (*(args[cur_arg+1]) == 0) {
3859 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3860 file, linenum, args[0], args[1], args[cur_arg]);
3861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
3863 }
3864 mysqluser = args[cur_arg + 1];
3865 userlen = strlen(mysqluser);
3866 packetlen = userlen + 7;
3867 reqlen = packetlen + 9;
3868
3869 free(curproxy->check_req);
3870 curproxy->check_req = (char *)calloc(1, reqlen);
3871 curproxy->check_len = reqlen;
3872
3873 snprintf(curproxy->check_req, 4, "%c%c%c",
3874 ((unsigned char) packetlen & 0xff),
3875 ((unsigned char) (packetlen >> 8) & 0xff),
3876 ((unsigned char) (packetlen >> 16) & 0xff));
3877
3878 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003879 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003880 curproxy->check_req[8] = 1;
3881 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3882 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3883 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3884 cur_arg += 2;
3885 } else {
3886 /* unknown suboption - catchall */
3887 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3888 file, linenum, args[0], args[1]);
3889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
3891 }
3892 } /* end while loop */
3893 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003894 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003895 else if (!strcmp(args[1], "ldap-check")) {
3896 /* use LDAP request to check servers' health */
3897 free(curproxy->check_req);
3898 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003899 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003900 curproxy->options2 |= PR_O2_LDAP_CHK;
3901
3902 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3903 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3904 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3905 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003906 else if (!strcmp(args[1], "tcp-check")) {
3907 /* use raw TCPCHK send/expect to check servers' health */
3908 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3909 err_code |= ERR_WARN;
3910
3911 free(curproxy->check_req);
3912 curproxy->check_req = NULL;
3913 curproxy->options2 &= ~PR_O2_CHK_ANY;
3914 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3915 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003916 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003917 int cur_arg;
3918
3919 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3920 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003921 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003922
Willy Tarreau87cf5142011-08-19 22:57:24 +02003923 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003924
3925 free(curproxy->fwdfor_hdr_name);
3926 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3927 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3928
3929 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3930 cur_arg = 2;
3931 while (*(args[cur_arg])) {
3932 if (!strcmp(args[cur_arg], "except")) {
3933 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003934 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003935 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3936 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003939 }
3940 /* flush useless bits */
3941 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003942 cur_arg += 2;
3943 } else if (!strcmp(args[cur_arg], "header")) {
3944 /* suboption header - needs additional argument for it */
3945 if (*(args[cur_arg+1]) == 0) {
3946 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3947 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003950 }
3951 free(curproxy->fwdfor_hdr_name);
3952 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3953 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3954 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003955 } else if (!strcmp(args[cur_arg], "if-none")) {
3956 curproxy->options &= ~PR_O_FF_ALWAYS;
3957 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003958 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003959 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003960 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003961 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003962 err_code |= ERR_ALERT | ERR_FATAL;
3963 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003964 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003965 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003966 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003967 else if (!strcmp(args[1], "originalto")) {
3968 int cur_arg;
3969
3970 /* insert x-original-to field, but not for the IP address listed as an except.
3971 * set default options (ie: bitfield, header name, etc)
3972 */
3973
3974 curproxy->options |= PR_O_ORGTO;
3975
3976 free(curproxy->orgto_hdr_name);
3977 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3978 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3979
Willy Tarreau87cf5142011-08-19 22:57:24 +02003980 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003981 cur_arg = 2;
3982 while (*(args[cur_arg])) {
3983 if (!strcmp(args[cur_arg], "except")) {
3984 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003985 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 +02003986 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3987 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003990 }
3991 /* flush useless bits */
3992 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3993 cur_arg += 2;
3994 } else if (!strcmp(args[cur_arg], "header")) {
3995 /* suboption header - needs additional argument for it */
3996 if (*(args[cur_arg+1]) == 0) {
3997 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3998 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004001 }
4002 free(curproxy->orgto_hdr_name);
4003 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4004 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4005 cur_arg += 2;
4006 } else {
4007 /* unknown suboption - catchall */
4008 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4009 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004012 }
4013 } /* end while loop */
4014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 else {
4016 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 }
Willy Tarreau93893792009-07-23 13:19:11 +02004020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004022 else if (!strcmp(args[0], "default_backend")) {
4023 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004025
4026 if (*(args[1]) == 0) {
4027 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004030 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004031 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004032 curproxy->defbe.name = strdup(args[1]);
4033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004037
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004038 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4039 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004040 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 /* enable reconnections to dispatch */
4042 curproxy->options |= PR_O_REDISP;
4043 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004044 else if (!strcmp(args[0], "http-check")) {
4045 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004047
4048 if (strcmp(args[1], "disable-on-404") == 0) {
4049 /* enable a graceful server shutdown on an HTTP 404 response */
4050 curproxy->options |= PR_O_DISABLE404;
4051 }
Willy Tarreauef781042010-01-27 11:53:01 +01004052 else if (strcmp(args[1], "send-state") == 0) {
4053 /* enable emission of the apparent state of a server in HTTP checks */
4054 curproxy->options2 |= PR_O2_CHK_SNDST;
4055 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004056 else if (strcmp(args[1], "expect") == 0) {
4057 const char *ptr_arg;
4058 int cur_arg;
4059
4060 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4061 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065
4066 cur_arg = 2;
4067 /* consider exclamation marks, sole or at the beginning of a word */
4068 while (*(ptr_arg = args[cur_arg])) {
4069 while (*ptr_arg == '!') {
4070 curproxy->options2 ^= PR_O2_EXP_INV;
4071 ptr_arg++;
4072 }
4073 if (*ptr_arg)
4074 break;
4075 cur_arg++;
4076 }
4077 /* now ptr_arg points to the beginning of a word past any possible
4078 * exclamation mark, and cur_arg is the argument which holds this word.
4079 */
4080 if (strcmp(ptr_arg, "status") == 0) {
4081 if (!*(args[cur_arg + 1])) {
4082 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4083 file, linenum, args[0], args[1], ptr_arg);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004088 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004089 curproxy->expect_str = strdup(args[cur_arg + 1]);
4090 }
4091 else if (strcmp(ptr_arg, "string") == 0) {
4092 if (!*(args[cur_arg + 1])) {
4093 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4094 file, linenum, args[0], args[1], ptr_arg);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
4098 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004099 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004100 curproxy->expect_str = strdup(args[cur_arg + 1]);
4101 }
4102 else if (strcmp(ptr_arg, "rstatus") == 0) {
4103 if (!*(args[cur_arg + 1])) {
4104 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4105 file, linenum, args[0], args[1], ptr_arg);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004110 free(curproxy->expect_str);
4111 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4112 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004113 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4114 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4115 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4116 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120 }
4121 else if (strcmp(ptr_arg, "rstring") == 0) {
4122 if (!*(args[cur_arg + 1])) {
4123 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4124 file, linenum, args[0], args[1], ptr_arg);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004129 free(curproxy->expect_str);
4130 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4131 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004132 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4133 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4134 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4135 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
4139 }
4140 else {
4141 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4142 file, linenum, args[0], args[1], ptr_arg);
4143 err_code |= ERR_ALERT | ERR_FATAL;
4144 goto out;
4145 }
4146 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004147 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004148 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 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004151 }
4152 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004153 else if (!strcmp(args[0], "tcp-check")) {
4154 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4155 err_code |= ERR_WARN;
4156
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004157 if (strcmp(args[1], "connect") == 0) {
4158 const char *ptr_arg;
4159 int cur_arg;
4160 struct tcpcheck_rule *tcpcheck;
4161 struct list *l;
4162
4163 /* check if first rule is also a 'connect' action */
4164 l = (struct list *)&curproxy->tcpcheck_rules;
4165 if (l->p != l->n) {
4166 tcpcheck = (struct tcpcheck_rule *)l->n;
4167 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4168 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4169 file, linenum);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
4173 }
4174
4175 cur_arg = 2;
4176 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4177 tcpcheck->action = TCPCHK_ACT_CONNECT;
4178
4179 /* parsing each parameters to fill up the rule */
4180 while (*(ptr_arg = args[cur_arg])) {
4181 /* tcp port */
4182 if (strcmp(args[cur_arg], "port") == 0) {
4183 if ( (atol(args[cur_arg + 1]) > 65535) ||
4184 (atol(args[cur_arg + 1]) < 1) ){
4185 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4186 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190 tcpcheck->port = atol(args[cur_arg + 1]);
4191 cur_arg += 2;
4192 }
4193 /* send proxy protocol */
4194 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4195 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4196 cur_arg++;
4197 }
4198#ifdef USE_OPENSSL
4199 else if (strcmp(args[cur_arg], "ssl") == 0) {
4200 curproxy->options |= PR_O_TCPCHK_SSL;
4201 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4202 cur_arg++;
4203 }
4204#endif /* USE_OPENSSL */
4205 else {
4206#ifdef USE_OPENSSL
4207 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4208#else /* USE_OPENSSL */
4209 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4210#endif /* USE_OPENSSL */
4211 file, linenum, args[0], args[1], args[cur_arg]);
4212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
4214 }
4215
4216 }
4217
4218 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4219 }
4220 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004221 if (! *(args[2]) ) {
4222 /* SEND string expected */
4223 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4224 file, linenum, args[0], args[1], args[2]);
4225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
4227 } else {
4228 struct tcpcheck_rule *tcpcheck;
4229
4230 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4231
4232 tcpcheck->action = TCPCHK_ACT_SEND;
4233 tcpcheck->string_len = strlen(args[2]);
4234 tcpcheck->string = strdup(args[2]);
4235 tcpcheck->expect_regex = NULL;
4236
4237 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4238 }
4239 }
4240 else if (strcmp(args[1], "send-binary") == 0) {
4241 if (! *(args[2]) ) {
4242 /* SEND binary string expected */
4243 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4244 file, linenum, args[0], args[1], args[2]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 } else {
4248 struct tcpcheck_rule *tcpcheck;
4249 char *err = NULL;
4250
4251 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4252
4253 tcpcheck->action = TCPCHK_ACT_SEND;
4254 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4255 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4256 file, linenum, args[0], args[1], args[2], err);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260 tcpcheck->expect_regex = NULL;
4261
4262 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4263 }
4264 }
4265 else if (strcmp(args[1], "expect") == 0) {
4266 const char *ptr_arg;
4267 int cur_arg;
4268 int inverse = 0;
4269
4270 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4271 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275
4276 cur_arg = 2;
4277 /* consider exclamation marks, sole or at the beginning of a word */
4278 while (*(ptr_arg = args[cur_arg])) {
4279 while (*ptr_arg == '!') {
4280 inverse = !inverse;
4281 ptr_arg++;
4282 }
4283 if (*ptr_arg)
4284 break;
4285 cur_arg++;
4286 }
4287 /* now ptr_arg points to the beginning of a word past any possible
4288 * exclamation mark, and cur_arg is the argument which holds this word.
4289 */
4290 if (strcmp(ptr_arg, "binary") == 0) {
4291 if (!*(args[cur_arg + 1])) {
4292 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> 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 char *err = NULL;
4299
4300 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4301
4302 tcpcheck->action = TCPCHK_ACT_EXPECT;
4303 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4304 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4305 file, linenum, args[0], args[1], args[2], err);
4306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
4309 tcpcheck->expect_regex = NULL;
4310 tcpcheck->inverse = inverse;
4311
4312 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4313 }
4314 else if (strcmp(ptr_arg, "string") == 0) {
4315 if (!*(args[cur_arg + 1])) {
4316 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4317 file, linenum, args[0], args[1], ptr_arg);
4318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321 struct tcpcheck_rule *tcpcheck;
4322
4323 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4324
4325 tcpcheck->action = TCPCHK_ACT_EXPECT;
4326 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4327 tcpcheck->string = strdup(args[cur_arg + 1]);
4328 tcpcheck->expect_regex = NULL;
4329 tcpcheck->inverse = inverse;
4330
4331 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4332 }
4333 else if (strcmp(ptr_arg, "rstring") == 0) {
4334 if (!*(args[cur_arg + 1])) {
4335 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4336 file, linenum, args[0], args[1], ptr_arg);
4337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
4339 }
4340 struct tcpcheck_rule *tcpcheck;
4341
4342 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4343
4344 tcpcheck->action = TCPCHK_ACT_EXPECT;
4345 tcpcheck->string_len = 0;
4346 tcpcheck->string = NULL;
4347 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4348 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4349 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4350 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354 tcpcheck->inverse = inverse;
4355
4356 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4357 }
4358 else {
4359 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4360 file, linenum, args[0], args[1], ptr_arg);
4361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
4363 }
4364 }
4365 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004366 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004371 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004372 if (curproxy == &defproxy) {
4373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004376 }
4377
Willy Tarreaub80c2302007-11-30 20:51:32 +01004378 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004379 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004380
4381 if (strcmp(args[1], "fail") == 0) {
4382 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004383 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004384 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4385 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004388 }
4389
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004390 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4391 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4392 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004395 }
4396 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4397 }
4398 else {
4399 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004402 }
4403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404#ifdef TPROXY
4405 else if (!strcmp(args[0], "transparent")) {
4406 /* enable transparent proxy connections */
4407 curproxy->options |= PR_O_TRANSP;
4408 }
4409#endif
4410 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004411 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004413
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 if (*(args[1]) == 0) {
4415 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 }
4419 curproxy->maxconn = atol(args[1]);
4420 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004421 else if (!strcmp(args[0], "backlog")) { /* backlog */
4422 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004424
4425 if (*(args[1]) == 0) {
4426 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004429 }
4430 curproxy->backlog = atol(args[1]);
4431 }
Willy Tarreau86034312006-12-29 00:10:33 +01004432 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004433 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004434 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004435
Willy Tarreau86034312006-12-29 00:10:33 +01004436 if (*(args[1]) == 0) {
4437 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004440 }
4441 curproxy->fullconn = atol(args[1]);
4442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4444 if (*(args[1]) == 0) {
4445 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
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 Tarreaub3f32f52007-12-02 22:15:14 +01004449 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4450 if (err) {
4451 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4452 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004455 }
4456 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 }
4458 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004459 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004460 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004461 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004462
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 if (curproxy == &defproxy) {
4464 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004468 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004470
Willy Tarreau902636f2013-03-10 19:44:48 +01004471 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004472 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004473 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004474 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004475 goto out;
4476 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004477
4478 proto = protocol_by_family(sk->ss_family);
4479 if (!proto || !proto->connect) {
4480 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4481 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
4484 }
4485
4486 if (port1 != port2) {
4487 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4488 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= ERR_ALERT | ERR_FATAL;
4490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004492
4493 if (!port1) {
4494 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4495 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
4498 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004499
Willy Tarreaud5191e72010-02-09 20:50:45 +01004500 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004501 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 }
4503 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004504 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004506
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004507 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4508 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004513 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004514 /**
4515 * The syntax for hash-type config element is
4516 * hash-type {map-based|consistent} [[<algo>] avalanche]
4517 *
4518 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4519 */
4520 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004521
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4523 err_code |= ERR_WARN;
4524
4525 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004526 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4527 }
4528 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004529 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4530 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004531 else if (strcmp(args[1], "avalanche") == 0) {
4532 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]);
4533 err_code |= ERR_ALERT | ERR_FATAL;
4534 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004535 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004536 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004537 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
4540 }
Bhaskar98634f02013-10-29 23:30:51 -04004541
4542 /* set the hash function to use */
4543 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004544 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004545 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004546
4547 /* if consistent with no argument, then avalanche modifier is also applied */
4548 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4549 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004550 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004551 /* set the hash function */
4552 if (!strcmp(args[2], "sdbm")) {
4553 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4554 }
4555 else if (!strcmp(args[2], "djb2")) {
4556 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004557 } else if (!strcmp(args[2], "wt6")) {
4558 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004559 }
4560 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004561 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 -05004562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
4564 }
4565
4566 /* set the hash modifier */
4567 if (!strcmp(args[3], "avalanche")) {
4568 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4569 }
4570 else if (*args[3]) {
4571 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
4574 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004575 }
William Lallemanda73203e2012-03-12 12:48:57 +01004576 }
William Lallemanda73203e2012-03-12 12:48:57 +01004577 else if (strcmp(args[0], "unique-id-format") == 0) {
4578 if (!*(args[1])) {
4579 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
4582 }
William Lallemand3203ff42012-11-11 17:30:56 +01004583 if (*(args[2])) {
4584 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004588 free(curproxy->conf.uniqueid_format_string);
4589 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004590
Willy Tarreau62a61232013-04-12 18:13:46 +02004591 free(curproxy->conf.uif_file);
4592 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4593 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004594 }
William Lallemanda73203e2012-03-12 12:48:57 +01004595
4596 else if (strcmp(args[0], "unique-id-header") == 0) {
4597 if (!*(args[1])) {
4598 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
4602 free(curproxy->header_unique_id);
4603 curproxy->header_unique_id = strdup(args[1]);
4604 }
4605
William Lallemand723b73a2012-02-08 16:37:49 +01004606 else if (strcmp(args[0], "log-format") == 0) {
4607 if (!*(args[1])) {
4608 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4609 err_code |= ERR_ALERT | ERR_FATAL;
4610 goto out;
4611 }
William Lallemand3203ff42012-11-11 17:30:56 +01004612 if (*(args[2])) {
4613 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004617
Willy Tarreau62a61232013-04-12 18:13:46 +02004618 if (curproxy->conf.logformat_string != default_http_log_format &&
4619 curproxy->conf.logformat_string != default_tcp_log_format &&
4620 curproxy->conf.logformat_string != clf_http_log_format)
4621 free(curproxy->conf.logformat_string);
4622 curproxy->conf.logformat_string = strdup(args[1]);
4623
4624 free(curproxy->conf.lfs_file);
4625 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4626 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004627
4628 /* get a chance to improve log-format error reporting by
4629 * reporting the correct line-number when possible.
4630 */
4631 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4632 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4633 file, linenum, curproxy->id);
4634 err_code |= ERR_WARN;
4635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636 }
William Lallemand723b73a2012-02-08 16:37:49 +01004637
William Lallemand0f99e342011-10-12 17:50:54 +02004638 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4639 /* delete previous herited or defined syslog servers */
4640 struct logsrv *back;
4641
4642 if (*(args[1]) != 0) {
4643 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
4646 }
4647
William Lallemand723b73a2012-02-08 16:37:49 +01004648 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4649 LIST_DEL(&tmplogsrv->list);
4650 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004651 }
4652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004653 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004654 struct logsrv *logsrv;
4655
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004657 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004658 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004659 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004660 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004661 LIST_INIT(&node->list);
4662 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 }
4665 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004666 struct sockaddr_storage *sk;
4667 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004668
4669 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670
William Lallemand0f99e342011-10-12 17:50:54 +02004671 logsrv->facility = get_log_facility(args[2]);
4672 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 }
4678
William Lallemand0f99e342011-10-12 17:50:54 +02004679 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004681 logsrv->level = get_log_level(args[3]);
4682 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004684 err_code |= ERR_ALERT | ERR_FATAL;
4685 goto out;
4686
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
4688 }
4689
William Lallemand0f99e342011-10-12 17:50:54 +02004690 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004691 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004692 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004693 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004694 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
4697
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004698 }
4699 }
4700
Willy Tarreau902636f2013-03-10 19:44:48 +01004701 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004702 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004703 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004704 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004705 goto out;
4706 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004707
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004708 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004709
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004710 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004711 if (port1 != port2) {
4712 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4713 file, linenum, args[0], args[1]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
4717
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004718 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004719 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720 }
William Lallemand0f99e342011-10-12 17:50:54 +02004721
4722 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 }
4724 else {
4725 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4726 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
4730 }
4731 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004732 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004733 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004734 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004735 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004736
Willy Tarreau977b8e42006-12-29 14:19:17 +01004737 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004738 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004739
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004741 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4742 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004746
4747 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004748 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4749 free(curproxy->conn_src.iface_name);
4750 curproxy->conn_src.iface_name = NULL;
4751 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004752
Willy Tarreau902636f2013-03-10 19:44:48 +01004753 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004754 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004755 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004756 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004757 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004758 goto out;
4759 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004760
4761 proto = protocol_by_family(sk->ss_family);
4762 if (!proto || !proto->connect) {
4763 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004764 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
4767 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004768
4769 if (port1 != port2) {
4770 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4771 file, linenum, args[0], args[1]);
4772 err_code |= ERR_ALERT | ERR_FATAL;
4773 goto out;
4774 }
4775
Willy Tarreauef9a3602012-12-08 22:29:20 +01004776 curproxy->conn_src.source_addr = *sk;
4777 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004778
4779 cur_arg = 2;
4780 while (*(args[cur_arg])) {
4781 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004782#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4783#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004784 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004785 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4786 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004789 }
4790#endif
4791 if (!*args[cur_arg + 1]) {
4792 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4793 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004796 }
4797
4798 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004799 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4800 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004801 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004802 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4803 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004804 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4805 char *name, *end;
4806
4807 name = args[cur_arg+1] + 7;
4808 while (isspace(*name))
4809 name++;
4810
4811 end = name;
4812 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4813 end++;
4814
Willy Tarreauef9a3602012-12-08 22:29:20 +01004815 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4816 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4817 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4818 curproxy->conn_src.bind_hdr_len = end - name;
4819 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4820 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4821 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004822
4823 /* now look for an occurrence number */
4824 while (isspace(*end))
4825 end++;
4826 if (*end == ',') {
4827 end++;
4828 name = end;
4829 if (*end == '-')
4830 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004831 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004832 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004833 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004834 }
4835
Willy Tarreauef9a3602012-12-08 22:29:20 +01004836 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004837 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4838 " occurrences values smaller than %d.\n",
4839 file, linenum, MAX_HDR_HISTORY);
4840 err_code |= ERR_ALERT | ERR_FATAL;
4841 goto out;
4842 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004843 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004844 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004845
Willy Tarreau902636f2013-03-10 19:44:48 +01004846 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004847 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004848 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004849 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004850 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004851 goto out;
4852 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004853
4854 proto = protocol_by_family(sk->ss_family);
4855 if (!proto || !proto->connect) {
4856 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4857 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004861
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004862 if (port1 != port2) {
4863 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4864 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004868 curproxy->conn_src.tproxy_addr = *sk;
4869 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004870 }
4871 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004872#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004873 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004874#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875#else /* no TPROXY support */
4876 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004877 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004880#endif
4881 cur_arg += 2;
4882 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004883 }
4884
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004885 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4886#ifdef SO_BINDTODEVICE
4887 if (!*args[cur_arg + 1]) {
4888 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4889 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004892 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004893 free(curproxy->conn_src.iface_name);
4894 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4895 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004896 global.last_checks |= LSTCHK_NETADM;
4897#else
4898 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4899 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004902#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004903 cur_arg += 2;
4904 continue;
4905 }
4906 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004907 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004912 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4913 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4914 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925
4926 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004927 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004928 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
4932 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004934 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004935 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004941 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004942 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
4946 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004948 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004949 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004960 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004966 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004967 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004969 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004970 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004973 }
4974 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004976 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004977 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4984 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988
4989 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004990 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004991 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004997 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004998 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005004 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005005 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
5009 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005011 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005012 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 }
5016 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005017 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005018 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005019 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005023 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005024 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005025 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005026 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005028 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005031 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005032
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 if (curproxy == &defproxy) {
5034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005038 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 if (*(args[1]) == 0) {
5042 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005046
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005047 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005048 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5049 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5050 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005054 err_code |= warnif_cond_conflicts(cond,
5055 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5056 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005057 }
5058 else if (*args[2]) {
5059 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5060 file, linenum, args[0], args[2]);
5061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
5063 }
5064
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005065 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005066 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005067 wl->s = strdup(args[1]);
5068 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005069 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 }
5071 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005072 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5074 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005075 err_code |= ERR_ALERT | ERR_FATAL;
5076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005077 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005078
Willy Tarreauade5ec42010-01-28 19:33:49 +01005079 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005080 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005081 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005082 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 }
5085 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005086 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005087 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005088 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005089 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 }
5092 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005093 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005094 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005095 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005096 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 }
5099 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005100 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
5106
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005108 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005109 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005110 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
5113 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005114 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005115 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005116 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 }
5120 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005121 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005122 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005123 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005128 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005129
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 if (curproxy == &defproxy) {
5131 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005135 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 if (*(args[1]) == 0) {
5139 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005144 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005145 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5146 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5147 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
5150 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005151 err_code |= warnif_cond_conflicts(cond,
5152 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5153 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005154 }
5155 else if (*args[2]) {
5156 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5157 file, linenum, args[0], args[2]);
5158 err_code |= ERR_ALERT | ERR_FATAL;
5159 goto out;
5160 }
5161
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005162 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005163 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005164 wl->s = strdup(args[1]);
5165 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167 else if (!strcmp(args[0], "errorloc") ||
5168 !strcmp(args[0], "errorloc302") ||
5169 !strcmp(args[0], "errorloc303")) { /* error location */
5170 int errnum, errlen;
5171 char *err;
5172
Willy Tarreau977b8e42006-12-29 14:19:17 +01005173 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005175
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005177 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181
5182 errnum = atol(args[1]);
5183 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005184 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5185 err = malloc(errlen);
5186 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005188 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5189 err = malloc(errlen);
5190 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
5192
Willy Tarreau0f772532006-12-23 20:51:41 +01005193 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5194 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005195 chunk_destroy(&curproxy->errmsg[rc]);
5196 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005197 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005200
5201 if (rc >= HTTP_ERR_SIZE) {
5202 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5203 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 free(err);
5205 }
5206 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005207 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5208 int errnum, errlen, fd;
5209 char *err;
5210 struct stat stat;
5211
5212 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005214
5215 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005216 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005219 }
5220
5221 fd = open(args[2], O_RDONLY);
5222 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5223 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5224 file, linenum, args[2], args[1]);
5225 if (fd >= 0)
5226 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229 }
5230
Willy Tarreau27a674e2009-08-17 07:23:33 +02005231 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005232 errlen = stat.st_size;
5233 } else {
5234 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005235 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005236 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005237 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005238 }
5239
5240 err = malloc(errlen); /* malloc() must succeed during parsing */
5241 errnum = read(fd, err, errlen);
5242 if (errnum != errlen) {
5243 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5244 file, linenum, args[2], args[1]);
5245 close(fd);
5246 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005249 }
5250 close(fd);
5251
5252 errnum = atol(args[1]);
5253 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5254 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005255 chunk_destroy(&curproxy->errmsg[rc]);
5256 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005257 break;
5258 }
5259 }
5260
5261 if (rc >= HTTP_ERR_SIZE) {
5262 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5263 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005265 free(err);
5266 }
5267 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005268 else if (!strcmp(args[0], "compression")) {
5269 struct comp *comp;
5270 if (curproxy->comp == NULL) {
5271 comp = calloc(1, sizeof(struct comp));
5272 curproxy->comp = comp;
5273 } else {
5274 comp = curproxy->comp;
5275 }
5276
5277 if (!strcmp(args[1], "algo")) {
5278 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005279 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005280
William Lallemand82fe75c2012-10-23 10:25:10 +02005281 cur_arg = 2;
5282 if (!*args[cur_arg]) {
5283 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5284 file, linenum, args[0]);
5285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
5287 }
5288 while (*(args[cur_arg])) {
5289 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5290 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5291 file, linenum, args[0], args[cur_arg]);
5292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
5294 }
William Lallemand552df672012-11-07 13:21:47 +01005295 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5296 curproxy->comp->algos->end(&ctx);
5297 } else {
5298 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5299 file, linenum, args[0], args[cur_arg]);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005303 cur_arg ++;
5304 continue;
5305 }
5306 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005307 else if (!strcmp(args[1], "offload")) {
5308 comp->offload = 1;
5309 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005310 else if (!strcmp(args[1], "type")) {
5311 int cur_arg;
5312 cur_arg = 2;
5313 if (!*args[cur_arg]) {
5314 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5315 file, linenum, args[0]);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
5319 while (*(args[cur_arg])) {
5320 comp_append_type(comp, args[cur_arg]);
5321 cur_arg ++;
5322 continue;
5323 }
5324 }
5325 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005326 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005327 file, linenum, args[0]);
5328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
5330 }
5331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005333 struct cfg_kw_list *kwl;
5334 int index;
5335
5336 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5337 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5338 if (kwl->kw[index].section != CFG_LISTEN)
5339 continue;
5340 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5341 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005342 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005343 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005344 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005347 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005348 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005349 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005350 err_code |= ERR_WARN;
5351 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005352 }
Willy Tarreau93893792009-07-23 13:19:11 +02005353 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005354 }
5355 }
5356 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005357
Willy Tarreau6daf3432008-01-22 16:44:08 +01005358 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 }
Willy Tarreau93893792009-07-23 13:19:11 +02005362 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005363 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005364 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365}
5366
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005367int
5368cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5369{
5370
5371 int err_code = 0;
5372 const char *err;
5373
5374 if (!strcmp(args[0], "userlist")) { /* new userlist */
5375 struct userlist *newul;
5376
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
5392 for (newul = userlist; newul; newul = newul->next)
5393 if (!strcmp(newul->name, args[1])) {
5394 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5395 file, linenum, args[1]);
5396 err_code |= ERR_WARN;
5397 goto out;
5398 }
5399
5400 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5401 if (!newul) {
5402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5403 err_code |= ERR_ALERT | ERR_ABORT;
5404 goto out;
5405 }
5406
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005407 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005408 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005409 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5410 err_code |= ERR_ALERT | ERR_ABORT;
5411 goto out;
5412 }
5413
5414 newul->next = userlist;
5415 userlist = newul;
5416
5417 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005418 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005419 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005420 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005421
5422 if (!*args[1]) {
5423 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5424 file, linenum, args[0]);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
5428
5429 err = invalid_char(args[1]);
5430 if (err) {
5431 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5432 file, linenum, *err, args[0], args[1]);
5433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
5435 }
5436
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005437 for (ag = userlist->groups; ag; ag = ag->next)
5438 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005439 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5440 file, linenum, args[1], userlist->name);
5441 err_code |= ERR_ALERT;
5442 goto out;
5443 }
5444
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005445 ag = calloc(1, sizeof(*ag));
5446 if (!ag) {
5447 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5448 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005449 goto out;
5450 }
5451
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005452 ag->name = strdup(args[1]);
5453 if (!ag) {
5454 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5455 err_code |= ERR_ALERT | ERR_ABORT;
5456 goto out;
5457 }
5458
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005459 cur_arg = 2;
5460
5461 while (*args[cur_arg]) {
5462 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005463 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005464 cur_arg += 2;
5465 continue;
5466 } else {
5467 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5468 file, linenum, args[0]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472 }
5473
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005474 ag->next = userlist->groups;
5475 userlist->groups = ag;
5476
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005477 } else if (!strcmp(args[0], "user")) { /* new user */
5478 struct auth_users *newuser;
5479 int cur_arg;
5480
5481 if (!*args[1]) {
5482 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5483 file, linenum, args[0]);
5484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
5486 }
5487
5488 for (newuser = userlist->users; newuser; newuser = newuser->next)
5489 if (!strcmp(newuser->user, args[1])) {
5490 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5491 file, linenum, args[1], userlist->name);
5492 err_code |= ERR_ALERT;
5493 goto out;
5494 }
5495
5496 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5497 if (!newuser) {
5498 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5499 err_code |= ERR_ALERT | ERR_ABORT;
5500 goto out;
5501 }
5502
5503 newuser->user = strdup(args[1]);
5504
5505 newuser->next = userlist->users;
5506 userlist->users = newuser;
5507
5508 cur_arg = 2;
5509
5510 while (*args[cur_arg]) {
5511 if (!strcmp(args[cur_arg], "password")) {
5512#ifndef CONFIG_HAP_CRYPT
5513 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5514 file, linenum);
5515 err_code |= ERR_ALERT;
5516#endif
5517 newuser->pass = strdup(args[cur_arg + 1]);
5518 cur_arg += 2;
5519 continue;
5520 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5521 newuser->pass = strdup(args[cur_arg + 1]);
5522 newuser->flags |= AU_O_INSECURE;
5523 cur_arg += 2;
5524 continue;
5525 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005526 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005527 cur_arg += 2;
5528 continue;
5529 } else {
5530 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5531 file, linenum, args[0]);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
5535 }
5536 } else {
5537 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 }
5540
5541out:
5542 return err_code;
5543}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544
5545/*
5546 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005547 * Returns the error code, 0 if OK, or any combination of :
5548 * - ERR_ABORT: must abort ASAP
5549 * - ERR_FATAL: we can continue parsing but not start the service
5550 * - ERR_WARN: a warning has been emitted
5551 * - ERR_ALERT: an alert has been emitted
5552 * Only the two first ones can stop processing, the two others are just
5553 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005555int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005557 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 FILE *f;
5559 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005560 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005561 struct cfg_section *cs = NULL;
5562 struct cfg_section *ics;
5563
5564 /* Register internal sections */
5565 if (!cfg_register_section("listen", cfg_parse_listen) ||
5566 !cfg_register_section("frontend", cfg_parse_listen) ||
5567 !cfg_register_section("backend", cfg_parse_listen) ||
5568 !cfg_register_section("ruleset", cfg_parse_listen) ||
5569 !cfg_register_section("defaults", cfg_parse_listen) ||
5570 !cfg_register_section("global", cfg_parse_global) ||
5571 !cfg_register_section("userlist", cfg_parse_users) ||
5572 !cfg_register_section("peers", cfg_parse_peers))
5573 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 if ((f=fopen(file,"r")) == NULL)
5576 return -1;
5577
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005578 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005579 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005580 char *end;
5581 char *args[MAX_LINE_ARGS + 1];
5582 char *line = thisline;
5583
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 linenum++;
5585
5586 end = line + strlen(line);
5587
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005588 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5589 /* Check if we reached the limit and the last char is not \n.
5590 * Watch out for the last line without the terminating '\n'!
5591 */
5592 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005593 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005595 }
5596
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005598 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 line++;
5600
5601 arg = 0;
5602 args[arg] = line;
5603
5604 while (*line && arg < MAX_LINE_ARGS) {
5605 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5606 * C equivalent value. Other combinations left unchanged (eg: \1).
5607 */
5608 if (*line == '\\') {
5609 int skip = 0;
5610 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5611 *line = line[1];
5612 skip = 1;
5613 }
5614 else if (line[1] == 'r') {
5615 *line = '\r';
5616 skip = 1;
5617 }
5618 else if (line[1] == 'n') {
5619 *line = '\n';
5620 skip = 1;
5621 }
5622 else if (line[1] == 't') {
5623 *line = '\t';
5624 skip = 1;
5625 }
5626 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005627 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 unsigned char hex1, hex2;
5629 hex1 = toupper(line[2]) - '0';
5630 hex2 = toupper(line[3]) - '0';
5631 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5632 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5633 *line = (hex1<<4) + hex2;
5634 skip = 3;
5635 }
5636 else {
5637 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 }
5640 }
5641 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005642 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 end -= skip;
5644 }
5645 line++;
5646 }
5647 else if (*line == '#' || *line == '\n' || *line == '\r') {
5648 /* end of string, end of loop */
5649 *line = 0;
5650 break;
5651 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005652 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005654 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005655 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 line++;
5657 args[++arg] = line;
5658 }
5659 else {
5660 line++;
5661 }
5662 }
5663
5664 /* empty line */
5665 if (!**args)
5666 continue;
5667
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005668 if (*line) {
5669 /* we had to stop due to too many args.
5670 * Let's terminate the string, print the offending part then cut the
5671 * last arg.
5672 */
5673 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5674 line++;
5675 *line = '\0';
5676
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005677 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005678 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005679 err_code |= ERR_ALERT | ERR_FATAL;
5680 args[arg] = line;
5681 }
5682
Willy Tarreau540abe42007-05-02 20:50:16 +02005683 /* zero out remaining args and ensure that at least one entry
5684 * is zeroed out.
5685 */
5686 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 args[arg] = line;
5688 }
5689
Willy Tarreau3842f002009-06-14 11:39:52 +02005690 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005691 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005692 char *tmp;
5693
Willy Tarreau3842f002009-06-14 11:39:52 +02005694 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005695 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005696 for (arg=0; *args[arg+1]; arg++)
5697 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005698 *tmp = '\0'; // fix the next arg to \0
5699 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005700 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005701 else if (!strcmp(args[0], "default")) {
5702 kwm = KWM_DEF;
5703 for (arg=0; *args[arg+1]; arg++)
5704 args[arg] = args[arg+1]; // shift args after inversion
5705 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005706
William Lallemand0f99e342011-10-12 17:50:54 +02005707 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5708 strcmp(args[0], "log") != 0) {
5709 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005711 }
5712
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005713 /* detect section start */
5714 list_for_each_entry(ics, &sections, list) {
5715 if (strcmp(args[0], ics->section_name) == 0) {
5716 cursection = ics->section_name;
5717 cs = ics;
5718 break;
5719 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005720 }
5721
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005723 if (cs)
5724 err_code |= cs->section_parser(file, linenum, args, kwm);
5725 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005726 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005727 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005729
5730 if (err_code & ERR_ABORT)
5731 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005732 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005733 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005735 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005736}
5737
Willy Tarreaubb925012009-07-23 13:36:36 +02005738/*
5739 * Returns the error code, 0 if OK, or any combination of :
5740 * - ERR_ABORT: must abort ASAP
5741 * - ERR_FATAL: we can continue parsing but not start the service
5742 * - ERR_WARN: a warning has been emitted
5743 * - ERR_ALERT: an alert has been emitted
5744 * Only the two first ones can stop processing, the two others are just
5745 * indicators.
5746 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005747int check_config_validity()
5748{
5749 int cfgerr = 0;
5750 struct proxy *curproxy = NULL;
5751 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005752 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005753 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005754 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005756 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 /*
5758 * Now, check for the integrity of all that we have collected.
5759 */
5760
5761 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005762 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763
Willy Tarreau193b8c62012-11-22 00:17:38 +01005764 if (!global.tune.max_http_hdr)
5765 global.tune.max_http_hdr = MAX_HTTP_HDR;
5766
5767 if (!global.tune.cookie_len)
5768 global.tune.cookie_len = CAPTURE_LEN;
5769
5770 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5771
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005772 /* Post initialisation of the users and groups lists. */
5773 err_code = userlist_postinit();
5774 if (err_code != ERR_NONE)
5775 goto out;
5776
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005777 /* first, we will invert the proxy list order */
5778 curproxy = NULL;
5779 while (proxy) {
5780 struct proxy *next;
5781
5782 next = proxy->next;
5783 proxy->next = curproxy;
5784 curproxy = proxy;
5785 if (!next)
5786 break;
5787 proxy = next;
5788 }
5789
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005791 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005792 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005793 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005794 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005795 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005796 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005797 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005798
Willy Tarreau050536d2012-10-04 08:47:34 +02005799 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005800 /* proxy ID not set, use automatic numbering with first
5801 * spare entry starting with next_pxid.
5802 */
5803 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5804 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5805 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005806 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005807 next_pxid++;
5808
Willy Tarreau55ea7572007-06-17 19:56:27 +02005809
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005811 /* ensure we don't keep listeners uselessly bound */
5812 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005813 curproxy = curproxy->next;
5814 continue;
5815 }
5816
Willy Tarreau16a21472012-11-19 12:39:59 +01005817 /* number of processes this proxy is bound to */
5818 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5819
Willy Tarreauff01a212009-03-15 13:46:16 +01005820 switch (curproxy->mode) {
5821 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005822 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005823 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005824 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5825 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005826 cfgerr++;
5827 }
5828
5829 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005830 Warning("config : servers will be ignored for %s '%s'.\n",
5831 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005832 break;
5833
5834 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005835 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005836 break;
5837
5838 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005839 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005840 break;
5841 }
5842
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005843 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005844 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005845 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005846 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5847 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005848 cfgerr++;
5849 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005851 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005852 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5853 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005854 cfgerr++;
5855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005857 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005858 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5859 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005860 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005861 }
5862 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005863 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005864 /* If no LB algo is set in a backend, and we're not in
5865 * transparent mode, dispatch mode nor proxy mode, we
5866 * want to use balance roundrobin by default.
5867 */
5868 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5869 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 }
5871 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005872
Willy Tarreau1620ec32011-08-06 17:05:02 +02005873 if (curproxy->options & PR_O_DISPATCH)
5874 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5875 else if (curproxy->options & PR_O_HTTP_PROXY)
5876 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5877 else if (curproxy->options & PR_O_TRANSP)
5878 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005879
Willy Tarreau1620ec32011-08-06 17:05:02 +02005880 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5881 if (curproxy->options & PR_O_DISABLE404) {
5882 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5883 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5884 err_code |= ERR_WARN;
5885 curproxy->options &= ~PR_O_DISABLE404;
5886 }
5887 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5888 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5889 "send-state", proxy_type_str(curproxy), curproxy->id);
5890 err_code |= ERR_WARN;
5891 curproxy->options &= ~PR_O2_CHK_SNDST;
5892 }
Willy Tarreauef781042010-01-27 11:53:01 +01005893 }
5894
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005895 /* if a default backend was specified, let's find it */
5896 if (curproxy->defbe.name) {
5897 struct proxy *target;
5898
Alex Williams96532db2009-11-01 21:27:13 -05005899 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005900 if (!target) {
5901 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5902 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005903 cfgerr++;
5904 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005905 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5906 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005907 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005908 } else {
5909 free(curproxy->defbe.name);
5910 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005911 /* we force the backend to be present on at least all of
5912 * the frontend's processes.
5913 */
5914 target->bind_proc = curproxy->bind_proc ?
5915 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005916
5917 /* Emit a warning if this proxy also has some servers */
5918 if (curproxy->srv) {
5919 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5920 curproxy->id);
5921 err_code |= ERR_WARN;
5922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 }
5924 }
5925
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005926 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005927 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5928 /* map jump target for ACT_SETBE in req_rep chain */
5929 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005930 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005931 struct proxy *target;
5932
Willy Tarreaua496b602006-12-17 23:15:24 +01005933 if (exp->action != ACT_SETBE)
5934 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005935
Alex Williams96532db2009-11-01 21:27:13 -05005936 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005937 if (!target) {
5938 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5939 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005940 cfgerr++;
5941 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005942 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5943 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005944 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005945 } else {
5946 free((void *)exp->replace);
5947 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005948 /* we force the backend to be present on at least all of
5949 * the frontend's processes.
5950 */
5951 target->bind_proc = curproxy->bind_proc ?
5952 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005953 }
5954 }
5955 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005956
5957 /* find the target proxy for 'use_backend' rules */
5958 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005959 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005960 struct logformat_node *node;
5961 char *pxname;
5962
5963 /* Try to parse the string as a log format expression. If the result
5964 * of the parsing is only one entry containing a simple string, then
5965 * it's a standard string corresponding to a static rule, thus the
5966 * parsing is cancelled and be.name is restored to be resolved.
5967 */
5968 pxname = rule->be.name;
5969 LIST_INIT(&rule->be.expr);
5970 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
5971 curproxy->conf.args.file, curproxy->conf.args.line);
5972 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
5973
5974 if (!LIST_ISEMPTY(&rule->be.expr)) {
5975 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
5976 rule->dynamic = 1;
5977 free(pxname);
5978 continue;
5979 }
5980 /* simple string: free the expression and fall back to static rule */
5981 free(node->arg);
5982 free(node);
5983 }
5984
5985 rule->dynamic = 0;
5986 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005987
Alex Williams96532db2009-11-01 21:27:13 -05005988 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005989
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005990 if (!target) {
5991 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5992 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005993 cfgerr++;
5994 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005995 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5996 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005997 cfgerr++;
5998 } else {
5999 free((void *)rule->be.name);
6000 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006001 /* we force the backend to be present on at least all of
6002 * the frontend's processes.
6003 */
6004 target->bind_proc = curproxy->bind_proc ?
6005 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006006 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006007 }
6008
6009 /* find the target proxy for 'use_backend' rules */
6010 list_for_each_entry(srule, &curproxy->server_rules, list) {
6011 struct server *target = findserver(curproxy, srule->srv.name);
6012
6013 if (!target) {
6014 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6015 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6016 cfgerr++;
6017 continue;
6018 }
6019 free((void *)srule->srv.name);
6020 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006021 }
6022
Emeric Brunb982a3d2010-01-04 15:45:53 +01006023 /* find the target table for 'stick' rules */
6024 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6025 struct proxy *target;
6026
Emeric Brun1d33b292010-01-04 15:47:17 +01006027 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6028 if (mrule->flags & STK_IS_STORE)
6029 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6030
Emeric Brunb982a3d2010-01-04 15:45:53 +01006031 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006032 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006033 else
6034 target = curproxy;
6035
6036 if (!target) {
6037 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6038 curproxy->id, mrule->table.name);
6039 cfgerr++;
6040 }
6041 else if (target->table.size == 0) {
6042 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6043 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6044 cfgerr++;
6045 }
Willy Tarreau12785782012-04-27 21:37:17 +02006046 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6047 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006048 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6049 cfgerr++;
6050 }
6051 else {
6052 free((void *)mrule->table.name);
6053 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006054 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006055 }
6056 }
6057
6058 /* find the target table for 'store response' rules */
6059 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6060 struct proxy *target;
6061
Emeric Brun1d33b292010-01-04 15:47:17 +01006062 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6063
Emeric Brunb982a3d2010-01-04 15:45:53 +01006064 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006065 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006066 else
6067 target = curproxy;
6068
6069 if (!target) {
6070 Alert("Proxy '%s': unable to find store table '%s'.\n",
6071 curproxy->id, mrule->table.name);
6072 cfgerr++;
6073 }
6074 else if (target->table.size == 0) {
6075 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6076 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6077 cfgerr++;
6078 }
Willy Tarreau12785782012-04-27 21:37:17 +02006079 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6080 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006081 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6082 cfgerr++;
6083 }
6084 else {
6085 free((void *)mrule->table.name);
6086 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006087 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006088 }
6089 }
6090
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006091 /* find the target table for 'tcp-request' layer 4 rules */
6092 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6093 struct proxy *target;
6094
Willy Tarreaub4c84932013-07-23 19:15:30 +02006095 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006096 continue;
6097
6098 if (trule->act_prm.trk_ctr.table.n)
6099 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6100 else
6101 target = curproxy;
6102
6103 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006104 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6105 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006106 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006107 cfgerr++;
6108 }
6109 else if (target->table.size == 0) {
6110 Alert("Proxy '%s': table '%s' used but not configured.\n",
6111 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6112 cfgerr++;
6113 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006114 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6115 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6116 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 +01006117 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006118 cfgerr++;
6119 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006120 else {
6121 free(trule->act_prm.trk_ctr.table.n);
6122 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006123 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006124 * to pass a list of counters to track and allocate them right here using
6125 * stktable_alloc_data_type().
6126 */
6127 }
6128 }
6129
Willy Tarreaud1f96522010-08-03 19:34:32 +02006130 /* find the target table for 'tcp-request' layer 6 rules */
6131 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6132 struct proxy *target;
6133
Willy Tarreaub4c84932013-07-23 19:15:30 +02006134 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006135 continue;
6136
6137 if (trule->act_prm.trk_ctr.table.n)
6138 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6139 else
6140 target = curproxy;
6141
6142 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006143 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6144 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006145 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006146 cfgerr++;
6147 }
6148 else if (target->table.size == 0) {
6149 Alert("Proxy '%s': table '%s' used but not configured.\n",
6150 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6151 cfgerr++;
6152 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006153 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6154 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6155 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 +01006156 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006157 cfgerr++;
6158 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006159 else {
6160 free(trule->act_prm.trk_ctr.table.n);
6161 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006162 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006163 * to pass a list of counters to track and allocate them right here using
6164 * stktable_alloc_data_type().
6165 */
6166 }
6167 }
6168
Emeric Brun32da3c42010-09-23 18:39:19 +02006169 if (curproxy->table.peers.name) {
6170 struct peers *curpeers = peers;
6171
6172 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6173 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6174 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006175 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006176 break;
6177 }
6178 }
6179
6180 if (!curpeers) {
6181 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6182 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006183 free((void *)curproxy->table.peers.name);
6184 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006185 cfgerr++;
6186 }
6187 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006188 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6189 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006190 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006191 cfgerr++;
6192 }
6193 }
6194
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006195 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006196 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006197 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6198 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6199 "proxy", curproxy->id);
6200 cfgerr++;
6201 goto out_uri_auth_compat;
6202 }
6203
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006204 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006205 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006206 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006207 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006208
Willy Tarreau95fa4692010-02-01 13:05:50 +01006209 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6210 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006211
6212 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006213 uri_auth_compat_req[i++] = "realm";
6214 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6215 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006216
Willy Tarreau95fa4692010-02-01 13:05:50 +01006217 uri_auth_compat_req[i++] = "unless";
6218 uri_auth_compat_req[i++] = "{";
6219 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6220 uri_auth_compat_req[i++] = "}";
6221 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006222
Willy Tarreauff011f22011-01-06 17:51:27 +01006223 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6224 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006225 cfgerr++;
6226 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006227 }
6228
Willy Tarreauff011f22011-01-06 17:51:27 +01006229 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006230
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006231 if (curproxy->uri_auth->auth_realm) {
6232 free(curproxy->uri_auth->auth_realm);
6233 curproxy->uri_auth->auth_realm = NULL;
6234 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006235
6236 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006237 }
6238out_uri_auth_compat:
6239
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006240 /* compile the log format */
6241 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006242 if (curproxy->conf.logformat_string != default_http_log_format &&
6243 curproxy->conf.logformat_string != default_tcp_log_format &&
6244 curproxy->conf.logformat_string != clf_http_log_format)
6245 free(curproxy->conf.logformat_string);
6246 curproxy->conf.logformat_string = NULL;
6247 free(curproxy->conf.lfs_file);
6248 curproxy->conf.lfs_file = NULL;
6249 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006250 }
6251
Willy Tarreau62a61232013-04-12 18:13:46 +02006252 if (curproxy->conf.logformat_string) {
6253 curproxy->conf.args.ctx = ARGC_LOG;
6254 curproxy->conf.args.file = curproxy->conf.lfs_file;
6255 curproxy->conf.args.line = curproxy->conf.lfs_line;
6256 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006257 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006258 curproxy->conf.args.file = NULL;
6259 curproxy->conf.args.line = 0;
6260 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006261
Willy Tarreau62a61232013-04-12 18:13:46 +02006262 if (curproxy->conf.uniqueid_format_string) {
6263 curproxy->conf.args.ctx = ARGC_UIF;
6264 curproxy->conf.args.file = curproxy->conf.uif_file;
6265 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006266 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006267 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6268 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006269 curproxy->conf.args.file = NULL;
6270 curproxy->conf.args.line = 0;
6271 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006272
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006273 /* only now we can check if some args remain unresolved.
6274 * This must be done after the users and groups resolution.
6275 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006276 cfgerr += smp_resolve_args(curproxy);
6277 if (!cfgerr)
6278 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006279
Willy Tarreau2738a142006-07-08 17:28:09 +02006280 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006281 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006282 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006283 (!curproxy->timeout.connect ||
6284 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006285 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006286 " | While not properly invalid, you will certainly encounter various problems\n"
6287 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006288 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006289 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006290 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006291 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006292
Willy Tarreau1fa31262007-12-03 00:36:16 +01006293 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6294 * We must still support older configurations, so let's find out whether those
6295 * parameters have been set or must be copied from contimeouts.
6296 */
6297 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006298 if (!curproxy->timeout.tarpit ||
6299 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006300 /* tarpit timeout not set. We search in the following order:
6301 * default.tarpit, curr.connect, default.connect.
6302 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006303 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006304 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006305 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006306 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006307 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006308 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006309 }
6310 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006311 (!curproxy->timeout.queue ||
6312 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006313 /* queue timeout not set. We search in the following order:
6314 * default.queue, curr.connect, default.connect.
6315 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006316 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006317 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006318 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006319 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006320 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006321 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006322 }
6323 }
6324
Willy Tarreau1620ec32011-08-06 17:05:02 +02006325 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006326 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6327 curproxy->check_req = (char *)malloc(curproxy->check_len);
6328 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006329 }
6330
Willy Tarreau193b8c62012-11-22 00:17:38 +01006331 /* ensure that cookie capture length is not too large */
6332 if (curproxy->capture_len >= global.tune.cookie_len) {
6333 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6334 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6335 err_code |= ERR_WARN;
6336 curproxy->capture_len = global.tune.cookie_len - 1;
6337 }
6338
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006339 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006340 if (curproxy->nb_req_cap) {
6341 if (curproxy->mode == PR_MODE_HTTP) {
6342 curproxy->req_cap_pool = create_pool("ptrcap",
6343 curproxy->nb_req_cap * sizeof(char *),
6344 MEM_F_SHARED);
6345 } else {
6346 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6347 proxy_type_str(curproxy), curproxy->id);
6348 err_code |= ERR_WARN;
6349 curproxy->to_log &= ~LW_REQHDR;
6350 curproxy->nb_req_cap = 0;
6351 }
6352 }
6353
6354 if (curproxy->nb_rsp_cap) {
6355 if (curproxy->mode == PR_MODE_HTTP) {
6356 curproxy->rsp_cap_pool = create_pool("ptrcap",
6357 curproxy->nb_rsp_cap * sizeof(char *),
6358 MEM_F_SHARED);
6359 } else {
6360 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6361 proxy_type_str(curproxy), curproxy->id);
6362 err_code |= ERR_WARN;
6363 curproxy->to_log &= ~LW_REQHDR;
6364 curproxy->nb_rsp_cap = 0;
6365 }
6366 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006367
Willy Tarreaubaaee002006-06-26 02:48:02 +02006368 /* first, we will invert the servers list order */
6369 newsrv = NULL;
6370 while (curproxy->srv) {
6371 struct server *next;
6372
6373 next = curproxy->srv->next;
6374 curproxy->srv->next = newsrv;
6375 newsrv = curproxy->srv;
6376 if (!next)
6377 break;
6378 curproxy->srv = next;
6379 }
6380
Willy Tarreau17edc812014-01-03 12:14:34 +01006381 /* Check that no server name conflicts. This causes trouble in the stats.
6382 * We only emit a warning for the first conflict affecting each server,
6383 * in order to avoid combinatory explosion if all servers have the same
6384 * name. We do that only for servers which do not have an explicit ID,
6385 * because these IDs were made also for distinguishing them and we don't
6386 * want to annoy people who correctly manage them.
6387 */
6388 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6389 struct server *other_srv;
6390
6391 if (newsrv->puid)
6392 continue;
6393
6394 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6395 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6396 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6397 newsrv->conf.file, newsrv->conf.line,
6398 proxy_type_str(curproxy), curproxy->id,
6399 newsrv->id, other_srv->conf.line);
6400 break;
6401 }
6402 }
6403 }
6404
Willy Tarreaudd701652010-05-25 23:03:02 +02006405 /* assign automatic UIDs to servers which don't have one yet */
6406 next_id = 1;
6407 newsrv = curproxy->srv;
6408 while (newsrv != NULL) {
6409 if (!newsrv->puid) {
6410 /* server ID not set, use automatic numbering with first
6411 * spare entry starting with next_svid.
6412 */
6413 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6414 newsrv->conf.id.key = newsrv->puid = next_id;
6415 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6416 }
6417 next_id++;
6418 newsrv = newsrv->next;
6419 }
6420
Willy Tarreau20697042007-11-15 23:26:18 +01006421 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006422 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423
Willy Tarreau62c3be22012-01-20 13:12:32 +01006424 /*
6425 * If this server supports a maxconn parameter, it needs a dedicated
6426 * tasks to fill the emptied slots when a connection leaves.
6427 * Also, resolve deferred tracking dependency if needed.
6428 */
6429 newsrv = curproxy->srv;
6430 while (newsrv != NULL) {
6431 if (newsrv->minconn > newsrv->maxconn) {
6432 /* Only 'minconn' was specified, or it was higher than or equal
6433 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6434 * this will avoid further useless expensive computations.
6435 */
6436 newsrv->maxconn = newsrv->minconn;
6437 } else if (newsrv->maxconn && !newsrv->minconn) {
6438 /* minconn was not specified, so we set it to maxconn */
6439 newsrv->minconn = newsrv->maxconn;
6440 }
6441
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006442#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006443 if (newsrv->use_ssl || newsrv->check.use_ssl)
6444 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006445#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006446
Willy Tarreau2f075e92013-12-03 11:11:34 +01006447 /* set the check type on the server */
6448 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6449
Willy Tarreau62c3be22012-01-20 13:12:32 +01006450 if (newsrv->trackit) {
6451 struct proxy *px;
6452 struct server *srv;
6453 char *pname, *sname;
6454
6455 pname = newsrv->trackit;
6456 sname = strrchr(pname, '/');
6457
6458 if (sname)
6459 *sname++ = '\0';
6460 else {
6461 sname = pname;
6462 pname = NULL;
6463 }
6464
6465 if (pname) {
6466 px = findproxy(pname, PR_CAP_BE);
6467 if (!px) {
6468 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6469 proxy_type_str(curproxy), curproxy->id,
6470 newsrv->id, pname);
6471 cfgerr++;
6472 goto next_srv;
6473 }
6474 } else
6475 px = curproxy;
6476
6477 srv = findserver(px, sname);
6478 if (!srv) {
6479 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6480 proxy_type_str(curproxy), curproxy->id,
6481 newsrv->id, sname);
6482 cfgerr++;
6483 goto next_srv;
6484 }
6485
Willy Tarreauff5ae352013-12-11 20:36:34 +01006486 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006487 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6488 "tracking as it does not have checks enabled.\n",
6489 proxy_type_str(curproxy), curproxy->id,
6490 newsrv->id, px->id, srv->id);
6491 cfgerr++;
6492 goto next_srv;
6493 }
6494
6495 if (curproxy != px &&
6496 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6497 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6498 "tracking: disable-on-404 option inconsistency.\n",
6499 proxy_type_str(curproxy), curproxy->id,
6500 newsrv->id, px->id, srv->id);
6501 cfgerr++;
6502 goto next_srv;
6503 }
6504
6505 /* if the other server is forced disabled, we have to do the same here */
6506 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006507 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006508 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006509 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006510 }
6511
6512 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006513 newsrv->tracknext = srv->trackers;
6514 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006515
6516 free(newsrv->trackit);
6517 newsrv->trackit = NULL;
6518 }
6519 next_srv:
6520 newsrv = newsrv->next;
6521 }
6522
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006523 /* We have to initialize the server lookup mechanism depending
6524 * on what LB algorithm was choosen.
6525 */
6526
6527 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6528 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6529 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006530 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6531 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6532 init_server_map(curproxy);
6533 } else {
6534 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6535 fwrr_init_server_groups(curproxy);
6536 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006537 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006538
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006539 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006540 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6541 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6542 fwlc_init_server_tree(curproxy);
6543 } else {
6544 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6545 fas_init_server_tree(curproxy);
6546 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006547 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006548
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006549 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006550 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6551 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6552 chash_init_server_tree(curproxy);
6553 } else {
6554 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6555 init_server_map(curproxy);
6556 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006557 break;
6558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559
6560 if (curproxy->options & PR_O_LOGASAP)
6561 curproxy->to_log &= ~LW_BYTES;
6562
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006563 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006564 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006565 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6566 proxy_type_str(curproxy), curproxy->id);
6567 err_code |= ERR_WARN;
6568 }
6569
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006570 if (curproxy->mode != PR_MODE_HTTP) {
6571 int optnum;
6572
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006573 if (curproxy->uri_auth) {
6574 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6575 proxy_type_str(curproxy), curproxy->id);
6576 err_code |= ERR_WARN;
6577 curproxy->uri_auth = NULL;
6578 }
6579
Willy Tarreau87cf5142011-08-19 22:57:24 +02006580 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006581 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6582 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6583 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006584 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006585 }
6586
6587 if (curproxy->options & PR_O_ORGTO) {
6588 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6589 "originalto", proxy_type_str(curproxy), curproxy->id);
6590 err_code |= ERR_WARN;
6591 curproxy->options &= ~PR_O_ORGTO;
6592 }
6593
6594 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6595 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6596 (curproxy->cap & cfg_opts[optnum].cap) &&
6597 (curproxy->options & cfg_opts[optnum].val)) {
6598 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6599 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6600 err_code |= ERR_WARN;
6601 curproxy->options &= ~cfg_opts[optnum].val;
6602 }
6603 }
6604
6605 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6606 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6607 (curproxy->cap & cfg_opts2[optnum].cap) &&
6608 (curproxy->options2 & cfg_opts2[optnum].val)) {
6609 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6610 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6611 err_code |= ERR_WARN;
6612 curproxy->options2 &= ~cfg_opts2[optnum].val;
6613 }
6614 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006615
Pieter Baauwd551fb52013-05-08 22:49:23 +02006616#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006617 if (curproxy->conn_src.bind_hdr_occ) {
6618 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006619 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006620 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006621 err_code |= ERR_WARN;
6622 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006623#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006624 }
6625
Willy Tarreaubaaee002006-06-26 02:48:02 +02006626 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006627 * ensure that we're not cross-dressing a TCP server into HTTP.
6628 */
6629 newsrv = curproxy->srv;
6630 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006631 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006632 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6633 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006634 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006635 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006636
Willy Tarreau0cec3312011-10-31 13:49:26 +01006637 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6638 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6639 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6640 err_code |= ERR_WARN;
6641 }
6642
Willy Tarreau82ffa392013-08-13 17:19:08 +02006643 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6644 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6645 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6646 err_code |= ERR_WARN;
6647 }
6648
Pieter Baauwd551fb52013-05-08 22:49:23 +02006649#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006650 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6651 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006652 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 +01006653 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006654 err_code |= ERR_WARN;
6655 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006656#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006657 newsrv = newsrv->next;
6658 }
6659
Willy Tarreauc1a21672009-08-16 22:37:44 +02006660 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006661 if (!curproxy->accept)
6662 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006663
Willy Tarreauc1a21672009-08-16 22:37:44 +02006664 if (curproxy->tcp_req.inspect_delay ||
6665 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006666 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006667
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006668 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006669 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006670 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006671 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006672
6673 /* both TCP and HTTP must check switching rules */
6674 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6675 }
6676
6677 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006678 if (curproxy->tcp_req.inspect_delay ||
6679 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6680 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6681
Emeric Brun97679e72010-09-23 17:56:44 +02006682 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6683 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6684
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006685 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006686 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006687 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006688 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006689
6690 /* If the backend does requires RDP cookie persistence, we have to
6691 * enable the corresponding analyser.
6692 */
6693 if (curproxy->options2 & PR_O2_RDPC_PRST)
6694 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6695 }
6696
Emeric Brunc52962f2012-11-15 18:28:02 +01006697#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006698 /* Configure SSL for each bind line.
6699 * Note: if configuration fails at some point, the ->ctx member
6700 * remains NULL so that listeners can later detach.
6701 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006702 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006703 if (!bind_conf->is_ssl) {
6704 if (bind_conf->default_ctx) {
6705 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6706 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6707 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006708 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006709 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006710 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006711 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006712 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006713 cfgerr++;
6714 continue;
6715 }
6716
Emeric Brun4b3091e2012-09-24 15:48:52 +02006717 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006718 Alert("Unable to allocate SSL session cache.\n");
6719 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006720 continue;
6721 }
6722
Emeric Brunfc0421f2012-09-07 17:30:07 +02006723 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006724 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006725 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006726#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006727
Willy Tarreaue6b98942007-10-29 01:09:36 +01006728 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006729 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006730 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006731 if (!listener->luid) {
6732 /* listener ID not set, use automatic numbering with first
6733 * spare entry starting with next_luid.
6734 */
6735 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6736 listener->conf.id.key = listener->luid = next_id;
6737 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006738 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006739 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006740
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006741 /* enable separate counters */
6742 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6743 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006744 if (!listener->name)
6745 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006746 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006747
Willy Tarreaue6b98942007-10-29 01:09:36 +01006748 if (curproxy->options & PR_O_TCP_NOLING)
6749 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006750 if (!listener->maxconn)
6751 listener->maxconn = curproxy->maxconn;
6752 if (!listener->backlog)
6753 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006754 if (!listener->maxaccept)
6755 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6756
6757 /* we want to have an optimal behaviour on single process mode to
6758 * maximize the work at once, but in multi-process we want to keep
6759 * some fairness between processes, so we target half of the max
6760 * number of events to be balanced over all the processes the proxy
6761 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6762 * used to disable the limit.
6763 */
6764 if (listener->maxaccept > 0) {
6765 if (nbproc > 1)
6766 listener->maxaccept = (listener->maxaccept + 1) / 2;
6767 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6768 }
6769
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006770 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006771 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006772 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006773 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006774
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006775 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6776 listener->options |= LI_O_TCP_RULES;
6777
Willy Tarreaude3041d2010-05-31 10:56:17 +02006778 if (curproxy->mon_mask.s_addr)
6779 listener->options |= LI_O_CHK_MONNET;
6780
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006781 /* smart accept mode is automatic in HTTP mode */
6782 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006783 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006784 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6785 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006786 }
6787
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006788 /* Release unused SSL configs */
6789 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6790 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006791 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006792#ifdef USE_OPENSSL
6793 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006794 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006795 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006796 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006797 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006798#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006799 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006800
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006801 /* Check multi-process mode compatibility for the current proxy */
6802 if (global.nbproc > 1) {
6803 int nbproc = 0;
6804 if (curproxy->bind_proc) {
6805 int proc;
6806 for (proc = 0; proc < global.nbproc; proc++) {
6807 if (curproxy->bind_proc & (1 << proc)) {
6808 nbproc++;
6809 }
6810 }
6811 } else {
6812 nbproc = global.nbproc;
6813 }
6814 if (curproxy->table.peers.name) {
6815 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6816 curproxy->id);
6817 cfgerr++;
6818 }
6819 if (nbproc > 1) {
6820 if (curproxy->uri_auth) {
6821 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6822 curproxy->id);
6823 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6824 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6825 curproxy->id);
6826 }
6827 }
6828 if (curproxy->appsession_name) {
6829 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6830 curproxy->id);
6831 }
6832 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6833 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6834 curproxy->id);
6835 }
6836 }
6837 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006838
6839 /* create the task associated with the proxy */
6840 curproxy->task = task_new();
6841 if (curproxy->task) {
6842 curproxy->task->context = curproxy;
6843 curproxy->task->process = manage_proxy;
6844 /* no need to queue, it will be done automatically if some
6845 * listener gets limited.
6846 */
6847 curproxy->task->expire = TICK_ETERNITY;
6848 } else {
6849 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6850 curproxy->id);
6851 cfgerr++;
6852 }
6853
Willy Tarreaubaaee002006-06-26 02:48:02 +02006854 curproxy = curproxy->next;
6855 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006856
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006857 /* Check multi-process mode compatibility */
6858 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006859 if (global.stats_fe && !global.stats_fe->bind_proc) {
6860 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 +01006861 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006862 }
6863
6864 /* automatically compute fullconn if not set. We must not do it in the
6865 * loop above because cross-references are not yet fully resolved.
6866 */
6867 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6868 /* If <fullconn> is not set, let's set it to 10% of the sum of
6869 * the possible incoming frontend's maxconns.
6870 */
6871 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6872 struct proxy *fe;
6873 int total = 0;
6874
6875 /* sum up the number of maxconns of frontends which
6876 * reference this backend at least once or which are
6877 * the same one ('listen').
6878 */
6879 for (fe = proxy; fe; fe = fe->next) {
6880 struct switching_rule *rule;
6881 struct hdr_exp *exp;
6882 int found = 0;
6883
6884 if (!(fe->cap & PR_CAP_FE))
6885 continue;
6886
6887 if (fe == curproxy) /* we're on a "listen" instance */
6888 found = 1;
6889
6890 if (fe->defbe.be == curproxy) /* "default_backend" */
6891 found = 1;
6892
6893 /* check if a "use_backend" rule matches */
6894 if (!found) {
6895 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006896 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006897 found = 1;
6898 break;
6899 }
6900 }
6901 }
6902
6903 /* check if a "reqsetbe" rule matches */
6904 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6905 if (exp->action == ACT_SETBE &&
6906 (struct proxy *)exp->replace == curproxy) {
6907 found = 1;
6908 break;
6909 }
6910 }
6911
6912 /* now we've checked all possible ways to reference a backend
6913 * from a frontend.
6914 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006915 if (!found)
6916 continue;
6917 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006918 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006919 /* we have the sum of the maxconns in <total>. We only
6920 * keep 10% of that sum to set the default fullconn, with
6921 * a hard minimum of 1 (to avoid a divide by zero).
6922 */
6923 curproxy->fullconn = (total + 9) / 10;
6924 if (!curproxy->fullconn)
6925 curproxy->fullconn = 1;
6926 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006927 }
6928
Willy Tarreau056f5682010-06-06 15:51:11 +02006929 /* initialize stick-tables on backend capable proxies. This must not
6930 * be done earlier because the data size may be discovered while parsing
6931 * other proxies.
6932 */
Godbach9703e662013-12-11 21:11:41 +08006933 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006934 if (curproxy->state == PR_STSTOPPED)
6935 continue;
6936
Godbach9703e662013-12-11 21:11:41 +08006937 if (!stktable_init(&curproxy->table)) {
6938 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6939 cfgerr++;
6940 }
6941 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006942
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006943 /*
6944 * Recount currently required checks.
6945 */
6946
6947 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6948 int optnum;
6949
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006950 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6951 if (curproxy->options & cfg_opts[optnum].val)
6952 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006953
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006954 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6955 if (curproxy->options2 & cfg_opts2[optnum].val)
6956 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006957 }
6958
Willy Tarreau122541c2011-09-07 21:24:49 +02006959 if (peers) {
6960 struct peers *curpeers = peers, **last;
6961 struct peer *p, *pb;
6962
6963 /* Remove all peers sections which don't have a valid listener.
6964 * This can happen when a peers section is never referenced and
6965 * does not contain a local peer.
6966 */
6967 last = &peers;
6968 while (*last) {
6969 curpeers = *last;
6970 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01006971 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02006972 last = &curpeers->next;
6973 continue;
6974 }
6975
6976 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6977 curpeers->id, localpeer);
6978
6979 p = curpeers->remote;
6980 while (p) {
6981 pb = p->next;
6982 free(p->id);
6983 free(p);
6984 p = pb;
6985 }
6986
6987 /* Destroy and unlink this curpeers section.
6988 * Note: curpeers is backed up into *last.
6989 */
6990 free(curpeers->id);
6991 curpeers = curpeers->next;
6992 free(*last);
6993 *last = curpeers;
6994 }
6995 }
6996
Willy Tarreau34eb6712011-10-24 18:15:04 +02006997 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006998 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006999 MEM_F_SHARED);
7000
Willy Tarreaubb925012009-07-23 13:36:36 +02007001 if (cfgerr > 0)
7002 err_code |= ERR_ALERT | ERR_FATAL;
7003 out:
7004 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005}
7006
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007007/*
7008 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7009 * parsing sessions.
7010 */
7011void cfg_register_keywords(struct cfg_kw_list *kwl)
7012{
7013 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7014}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007015
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007016/*
7017 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7018 */
7019void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7020{
7021 LIST_DEL(&kwl->list);
7022 LIST_INIT(&kwl->list);
7023}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007025/* this function register new section in the haproxy configuration file.
7026 * <section_name> is the name of this new section and <section_parser>
7027 * is the called parser. If two section declaration have the same name,
7028 * only the first declared is used.
7029 */
7030int cfg_register_section(char *section_name,
7031 int (*section_parser)(const char *, int, char **, int))
7032{
7033 struct cfg_section *cs;
7034
7035 cs = calloc(1, sizeof(*cs));
7036 if (!cs) {
7037 Alert("register section '%s': out of memory.\n", section_name);
7038 return 0;
7039 }
7040
7041 cs->section_name = section_name;
7042 cs->section_parser = section_parser;
7043
7044 LIST_ADDQ(&sections, &cs->list);
7045
7046 return 1;
7047}
7048
Willy Tarreaubaaee002006-06-26 02:48:02 +02007049/*
7050 * Local variables:
7051 * c-indent-level: 8
7052 * c-basic-offset: 8
7053 * End:
7054 */