blob: 762978a6ccbfc6d58126fb09e7c87da838b8754d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100113/* permit to store configuration section */
114struct cfg_section {
115 struct list list;
116 char *section_name;
117 int (*section_parser)(const char *, int, char **, int);
118};
119
120/* Used to chain configuration sections definitions. This list
121 * stores struct cfg_section
122 */
123struct list sections = LIST_HEAD_INIT(sections);
124
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100126struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127 const char *name;
128 unsigned int val;
129 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100130 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100132};
133
134/* proxy->options */
135static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
138 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
139 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
140 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
141 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
142 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100144 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
146 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
147 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
148 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
149 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100150#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100152#else
153 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100154#endif
155
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100157};
158
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159/* proxy->options2 */
160static const struct cfg_opt cfg_opts2[] =
161{
162#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
165 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "splice-request", 0, 0, 0, 0 },
168 { "splice-response", 0, 0, 0, 0 },
169 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
172 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
173 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
174 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
175 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
176 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
177 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
178 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
179 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400180 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200182 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200183 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184 { NULL, 0, 0, 0 }
185};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186
Willy Tarreau6daf3432008-01-22 16:44:08 +0100187static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
189int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100190int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200192/* List head of all known configuration keywords */
193static struct cfg_kw_list cfg_keywords = {
194 .list = LIST_HEAD_INIT(cfg_keywords.list)
195};
196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197/*
198 * converts <str> to a list of listeners which are dynamically allocated.
199 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
200 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
201 * - <port> is a numerical port from 1 to 65535 ;
202 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
203 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200204 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
205 * not NULL, it must be a valid pointer to either NULL or a freeable area that
206 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200208int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209{
210 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 int port, end;
213
214 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100218 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
220 str = next;
221 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100222 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 *next++ = 0;
224 }
225
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100226 ss2 = str2sa_range(str, &port, &end, err,
227 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
228 if (!ss2)
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100232 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200233 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100237 if (!port || !end) {
238 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
239 goto fail;
240 }
241
Emeric Bruned760922010-10-22 17:59:25 +0200242 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200244 goto fail;
245 }
246
247 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100252 else if (ss2->ss_family == AF_UNSPEC) {
253 socklen_t addr_len;
254
255 /* We want to attach to an already bound fd whose number
256 * is in the addr part of ss2 when cast to sockaddr_in.
257 * Note that by definition there is a single listener.
258 * We still have to determine the address family to
259 * register the correct protocol.
260 */
261 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
262 addr_len = sizeof(*ss2);
263 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
264 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
265 goto fail;
266 }
267
268 port = end = get_host_port(ss2);
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100271 /* OK the address looks correct */
272 ss = *ss2;
273
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 for (; port <= end; port++) {
275 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100276 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200277 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
278 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
279 l->frontend = curproxy;
280 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200284 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 l->state = LI_INIT;
286
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100287 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 tcpv4_add_listener(l);
290 }
Emeric Bruned760922010-10-22 17:59:25 +0200291 else if (ss.ss_family == AF_INET6) {
292 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
293 tcpv6_add_listener(l);
294 }
295 else {
Emeric Bruned760922010-10-22 17:59:25 +0200296 uxst_add_listener(l);
297 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200299 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 } /* end for(port) */
302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
Willy Tarreau61d18892009-03-31 10:49:21 +0200310/* Report a warning if a rule is placed after a 'block' rule.
311 * Return 1 if the warning has been emitted, otherwise 0.
312 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100313int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200314{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200315 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200316 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
317 file, line, arg);
318 return 1;
319 }
320 return 0;
321}
322
Willy Tarreau5002f572014-04-23 01:32:02 +0200323/* Report a warning if a rule is placed after an 'http_request' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
327{
328 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
Willy Tarreau61d18892009-03-31 10:49:21 +0200336/* Report a warning if a rule is placed after a reqrewrite rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
341 if (proxy->req_exp) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a reqadd rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100354 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a redirect rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a 'use_backend' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
Willy Tarreauee445d92014-04-23 01:39:04 +0200388/* Report a warning if a rule is placed after a 'use-server' rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
391int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
392{
393 if (!LIST_ISEMPTY(&proxy->server_rules)) {
394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
Willy Tarreau61d18892009-03-31 10:49:21 +0200401/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
Willy Tarreau5002f572014-04-23 01:32:02 +0200404 return warnif_rule_after_http_req(proxy, file, line, arg) ||
405 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
406 warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200408 warnif_rule_after_use_backend(proxy, file, line, arg) ||
409 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200410}
411
412/* report a warning if an http-request rule is dangerously placed */
413int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
414{
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200420}
421
422/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
425 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
426 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200427 warnif_rule_after_use_backend(proxy, file, line, arg) ||
428 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200429}
430
431/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100432int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200433{
434 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a redirect rule is dangerously placed */
440int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
443 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200444}
445
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446/* Report it if a request ACL condition uses some keywords that are incompatible
447 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
448 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
449 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100451static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100453 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200454 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100457 return 0;
458
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100459 acl = acl_cond_conflicts(cond, where);
460 if (acl) {
461 if (acl->name && *acl->name)
462 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
463 file, line, acl->name, sample_ckp_names(where));
464 else
465 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200466 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100467 return ERR_WARN;
468 }
469 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100470 return 0;
471
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100472 if (acl->name && *acl->name)
473 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200474 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100475 else
476 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200477 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100478 return ERR_WARN;
479}
480
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 * parse a line in a <global> section. Returns the error code, 0 if OK, or
483 * any combination of :
484 * - ERR_ABORT: must abort ASAP
485 * - ERR_FATAL: we can continue parsing but not start the service
486 * - ERR_WARN: a warning has been emitted
487 * - ERR_ALERT: an alert has been emitted
488 * Only the two first ones can stop processing, the two others are just
489 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200491int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492{
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200494 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (!strcmp(args[0], "global")) { /* new section */
497 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200500 else if (!strcmp(args[0], "ca-base")) {
501#ifdef USE_OPENSSL
502 if (global.ca_base != NULL) {
503 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT;
505 goto out;
506 }
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 global.ca_base = strdup(args[1]);
513#else
514 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517#endif
518 }
519 else if (!strcmp(args[0], "crt-base")) {
520#ifdef USE_OPENSSL
521 if (global.crt_base != NULL) {
522 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT;
524 goto out;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 global.crt_base = strdup(args[1]);
532#else
533 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536#endif
537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "daemon")) {
539 global.mode |= MODE_DAEMON;
540 }
541 else if (!strcmp(args[0], "debug")) {
542 global.mode |= MODE_DEBUG;
543 }
544 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100545 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200547 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100548 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100551 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100553 else if (!strcmp(args[0], "nosplice")) {
554 global.tune.options &= ~GTUNE_USE_SPLICE;
555 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200556 else if (!strcmp(args[0], "nogetaddrinfo")) {
557 global.tune.options &= ~GTUNE_USE_GAI;
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 else if (!strcmp(args[0], "quiet")) {
560 global.mode |= MODE_QUIET;
561 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200562 else if (!strcmp(args[0], "tune.maxpollevents")) {
563 if (global.tune.maxpollevents != 0) {
564 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200565 err_code |= ERR_ALERT;
566 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200567 }
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 }
573 global.tune.maxpollevents = atol(args[1]);
574 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100575 else if (!strcmp(args[0], "tune.maxaccept")) {
576 if (global.tune.maxaccept != 0) {
577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100580 }
581 if (*(args[1]) == 0) {
582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 }
586 global.tune.maxaccept = atol(args[1]);
587 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200588 else if (!strcmp(args[0], "tune.chksize")) {
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.chksize = atol(args[1]);
595 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200596#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200597 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
598 global.tune.sslprivatecache = 1;
599 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100600 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.sslcachesize = atol(args[1]);
607 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100608 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
609 unsigned int ssllifetime;
610 const char *res;
611
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617
618 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
619 if (res) {
620 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
621 file, linenum, *res, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625
626 global.tune.ssllifetime = ssllifetime;
627 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100628 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.ssl_max_record = atol(args[1]);
635 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200636 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.ssl_default_dh_param = atol(args[1]);
643 if (global.tune.ssl_default_dh_param < 1024) {
644 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200650 else if (!strcmp(args[0], "tune.bufsize")) {
651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.bufsize = atol(args[1]);
657 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
658 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100659 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100660 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200661 }
662 else if (!strcmp(args[0], "tune.maxrewrite")) {
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668 global.tune.maxrewrite = atol(args[1]);
669 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
670 global.tune.maxrewrite = global.tune.bufsize / 2;
671 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100672 else if (!strcmp(args[0], "tune.idletimer")) {
673 unsigned int idle;
674 const char *res;
675
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681
682 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
683 if (res) {
684 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
685 file, linenum, *res, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689
690 if (idle > 65535) {
691 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.idle_timer = idle;
696 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100697 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
698 if (global.tune.client_rcvbuf != 0) {
699 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
700 err_code |= ERR_ALERT;
701 goto out;
702 }
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.client_rcvbuf = atol(args[1]);
709 }
710 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
711 if (global.tune.server_rcvbuf != 0) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT;
714 goto out;
715 }
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.tune.server_rcvbuf = atol(args[1]);
722 }
723 else if (!strcmp(args[0], "tune.sndbuf.client")) {
724 if (global.tune.client_sndbuf != 0) {
725 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT;
727 goto out;
728 }
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.client_sndbuf = atol(args[1]);
735 }
736 else if (!strcmp(args[0], "tune.sndbuf.server")) {
737 if (global.tune.server_sndbuf != 0) {
738 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT;
740 goto out;
741 }
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.server_sndbuf = atol(args[1]);
748 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200749 else if (!strcmp(args[0], "tune.pipesize")) {
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.pipesize = atol(args[1]);
756 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100757 else if (!strcmp(args[0], "tune.http.cookielen")) {
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 global.tune.cookie_len = atol(args[1]) + 1;
764 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200765 else if (!strcmp(args[0], "tune.http.maxhdr")) {
766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 global.tune.max_http_hdr = atol(args[1]);
772 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100773 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
774#ifdef USE_ZLIB
775 if (*args[1]) {
776 global.tune.zlibmemlevel = atoi(args[1]);
777 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
778 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
779 file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 } else {
784 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\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' is not implemented.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
793#endif
794 }
795 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
796#ifdef USE_ZLIB
797 if (*args[1]) {
798 global.tune.zlibwindowsize = atoi(args[1]);
799 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
800 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
801 file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805 } else {
806 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
807 file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811#else
812 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815#endif
816 }
William Lallemandf3747832012-11-09 12:33:10 +0100817 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
818 if (*args[1]) {
819 global.tune.comp_maxlevel = atoi(args[1]);
820 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
821 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
822 file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 } else {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 else if (!strcmp(args[0], "uid")) {
834 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200835 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200836 err_code |= ERR_ALERT;
837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 }
839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 }
844 global.uid = atol(args[1]);
845 }
846 else if (!strcmp(args[0], "gid")) {
847 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200848 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200849 err_code |= ERR_ALERT;
850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 }
852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 }
857 global.gid = atol(args[1]);
858 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200859 /* user/group name handling */
860 else if (!strcmp(args[0], "user")) {
861 struct passwd *ha_user;
862 if (global.uid != 0) {
863 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 err_code |= ERR_ALERT;
865 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200866 }
867 errno = 0;
868 ha_user = getpwnam(args[1]);
869 if (ha_user != NULL) {
870 global.uid = (int)ha_user->pw_uid;
871 }
872 else {
873 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 +0200874 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200875 }
876 }
877 else if (!strcmp(args[0], "group")) {
878 struct group *ha_group;
879 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200880 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200881 err_code |= ERR_ALERT;
882 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200883 }
884 errno = 0;
885 ha_group = getgrnam(args[1]);
886 if (ha_group != NULL) {
887 global.gid = (int)ha_group->gr_gid;
888 }
889 else {
890 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 +0200891 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200892 }
893 }
894 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100902 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
903 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
904 file, linenum, args[0], LONGBITS, global.nbproc);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 else if (!strcmp(args[0], "maxconn")) {
910 if (global.maxconn != 0) {
911 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 }
915 if (*(args[1]) == 0) {
916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 }
920 global.maxconn = atol(args[1]);
921#ifdef SYSTEM_MAXCONN
922 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
923 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);
924 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927#endif /* SYSTEM_MAXCONN */
928 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200929 else if (!strcmp(args[0], "maxsslconn")) {
930#ifdef USE_OPENSSL
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.maxsslconn = atol(args[1]);
937#else
Emeric Brun0914df82012-10-02 18:45:42 +0200938 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200941#endif
942 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100943 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
944#ifdef USE_OPENSSL
945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
949 }
950 free(global.listen_default_ciphers);
951 global.listen_default_ciphers = strdup(args[1]);
952#else
953 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956#endif
957 }
958 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
959#ifdef USE_OPENSSL
960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 free(global.connect_default_ciphers);
966 global.connect_default_ciphers = strdup(args[1]);
967#else
968 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
971#endif
972 }
Emeric Brun850efd52014-01-29 12:24:34 +0100973 else if (!strcmp(args[0], "ssl-server-verify")) {
974 if (*(args[1]) == 0) {
975 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979 if (strcmp(args[1],"none") == 0)
980 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
981 else if (strcmp(args[1],"required") == 0)
982 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
983 else {
984 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200989 else if (!strcmp(args[0], "maxconnrate")) {
990 if (global.cps_lim != 0) {
991 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
992 err_code |= ERR_ALERT;
993 goto out;
994 }
995 if (*(args[1]) == 0) {
996 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 global.cps_lim = atol(args[1]);
1001 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001002 else if (!strcmp(args[0], "maxsessrate")) {
1003 if (global.sps_lim != 0) {
1004 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1005 err_code |= ERR_ALERT;
1006 goto out;
1007 }
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 global.sps_lim = atol(args[1]);
1014 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001015 else if (!strcmp(args[0], "maxsslrate")) {
1016 if (global.ssl_lim != 0) {
1017 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT;
1019 goto out;
1020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 global.ssl_lim = atol(args[1]);
1027 }
William Lallemandd85f9172012-11-09 17:05:39 +01001028 else if (!strcmp(args[0], "maxcomprate")) {
1029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034 global.comp_rate_lim = atoi(args[1]) * 1024;
1035 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001036 else if (!strcmp(args[0], "maxpipes")) {
1037 if (global.maxpipes != 0) {
1038 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT;
1040 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001041 }
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001046 }
1047 global.maxpipes = atol(args[1]);
1048 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001049 else if (!strcmp(args[0], "maxzlibmem")) {
1050 if (*(args[1]) == 0) {
1051 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
1054 }
William Lallemande3a7d992012-11-20 11:25:20 +01001055 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001056 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001057 else if (!strcmp(args[0], "maxcompcpuusage")) {
1058 if (*(args[1]) == 0) {
1059 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062 }
1063 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001064 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001065 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069}
1070
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 else if (!strcmp(args[0], "ulimit-n")) {
1072 if (global.rlimit_nofile != 0) {
1073 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001074 err_code |= ERR_ALERT;
1075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 }
1077 if (*(args[1]) == 0) {
1078 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 }
1082 global.rlimit_nofile = atol(args[1]);
1083 }
1084 else if (!strcmp(args[0], "chroot")) {
1085 if (global.chroot != NULL) {
1086 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001087 err_code |= ERR_ALERT;
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
1090 if (*(args[1]) == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 }
1095 global.chroot = strdup(args[1]);
1096 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097 else if (!strcmp(args[0], "description")) {
1098 int i, len=0;
1099 char *d;
1100
1101 if (!*args[1]) {
1102 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1103 file, linenum, args[0]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
1107
Willy Tarreau348acfe2014-04-14 15:00:39 +02001108 for (i = 1; *args[i]; i++)
1109 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001110
1111 if (global.desc)
1112 free(global.desc);
1113
1114 global.desc = d = (char *)calloc(1, len);
1115
Willy Tarreau348acfe2014-04-14 15:00:39 +02001116 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1117 for (i = 2; *args[i]; i++)
1118 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001119 }
1120 else if (!strcmp(args[0], "node")) {
1121 int i;
1122 char c;
1123
1124 for (i=0; args[1][i]; i++) {
1125 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001126 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1127 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001128 break;
1129 }
1130
1131 if (!i || args[1][i]) {
1132 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1133 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1134 file, linenum, args[0]);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
1137 }
1138
1139 if (global.node)
1140 free(global.node);
1141
1142 global.node = strdup(args[1]);
1143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 else if (!strcmp(args[0], "pidfile")) {
1145 if (global.pidfile != NULL) {
1146 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
1150 if (*(args[1]) == 0) {
1151 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
1155 global.pidfile = strdup(args[1]);
1156 }
Emeric Bruned760922010-10-22 17:59:25 +02001157 else if (!strcmp(args[0], "unix-bind")) {
1158 int cur_arg = 1;
1159 while (*(args[cur_arg])) {
1160 if (!strcmp(args[cur_arg], "prefix")) {
1161 if (global.unix_bind.prefix != NULL) {
1162 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1163 err_code |= ERR_ALERT;
1164 cur_arg += 2;
1165 continue;
1166 }
1167
1168 if (*(args[cur_arg+1]) == 0) {
1169 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
1172 }
1173 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1174 cur_arg += 2;
1175 continue;
1176 }
1177
1178 if (!strcmp(args[cur_arg], "mode")) {
1179
1180 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1181 cur_arg += 2;
1182 continue;
1183 }
1184
1185 if (!strcmp(args[cur_arg], "uid")) {
1186
1187 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1188 cur_arg += 2;
1189 continue;
1190 }
1191
1192 if (!strcmp(args[cur_arg], "gid")) {
1193
1194 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1195 cur_arg += 2;
1196 continue;
1197 }
1198
1199 if (!strcmp(args[cur_arg], "user")) {
1200 struct passwd *user;
1201
1202 user = getpwnam(args[cur_arg + 1]);
1203 if (!user) {
1204 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1205 file, linenum, args[0], args[cur_arg + 1 ]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
1208 }
1209
1210 global.unix_bind.ux.uid = user->pw_uid;
1211 cur_arg += 2;
1212 continue;
1213 }
1214
1215 if (!strcmp(args[cur_arg], "group")) {
1216 struct group *group;
1217
1218 group = getgrnam(args[cur_arg + 1]);
1219 if (!group) {
1220 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1221 file, linenum, args[0], args[cur_arg + 1 ]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225
1226 global.unix_bind.ux.gid = group->gr_gid;
1227 cur_arg += 2;
1228 continue;
1229 }
1230
Willy Tarreaub48f9582011-09-05 01:17:06 +02001231 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001232 file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 }
William Lallemand0f99e342011-10-12 17:50:54 +02001237 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1238 /* delete previous herited or defined syslog servers */
1239 struct logsrv *back;
1240 struct logsrv *tmp;
1241
1242 if (*(args[1]) != 0) {
1243 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1244 err_code |= ERR_ALERT | ERR_FATAL;
1245 goto out;
1246 }
1247
1248 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1249 LIST_DEL(&tmp->list);
1250 free(tmp);
1251 }
1252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001254 struct sockaddr_storage *sk;
1255 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001256 struct logsrv *logsrv;
1257
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 if (*(args[1]) == 0 || *(args[2]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 }
William Lallemand0f99e342011-10-12 17:50:54 +02001263
1264 logsrv = calloc(1, sizeof(struct logsrv));
1265
1266 logsrv->facility = get_log_facility(args[2]);
1267 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001269 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001270 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 }
1272
William Lallemand0f99e342011-10-12 17:50:54 +02001273 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001275 logsrv->level = get_log_level(args[3]);
1276 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001279 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 }
1281 }
1282
William Lallemand0f99e342011-10-12 17:50:54 +02001283 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001284 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001285 logsrv->minlvl = get_log_level(args[4]);
1286 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001287 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001288 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001289 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001290 }
1291 }
1292
Willy Tarreau902636f2013-03-10 19:44:48 +01001293 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001294 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001295 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001297 free(logsrv);
1298 goto out;
1299 }
1300 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001301
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001302 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001303 if (port1 != port2) {
1304 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1305 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001306 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001307 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001308 goto out;
1309 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001310
William Lallemand0f99e342011-10-12 17:50:54 +02001311 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001312 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001313 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315
William Lallemand0f99e342011-10-12 17:50:54 +02001316 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001317 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001318 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1319 char *name;
1320 int len;
1321
1322 if (global.log_send_hostname != NULL) {
1323 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1324 err_code |= ERR_ALERT;
1325 goto out;
1326 }
1327
1328 if (*(args[1]))
1329 name = args[1];
1330 else
1331 name = hostname;
1332
1333 len = strlen(name);
1334
1335 /* We'll add a space after the name to respect the log format */
1336 free(global.log_send_hostname);
1337 global.log_send_hostname = malloc(len + 2);
1338 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1339 }
Kevinm48936af2010-12-22 16:08:21 +00001340 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1341 if (*(args[1]) == 0) {
1342 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
1345 }
1346 free(global.log_tag);
1347 global.log_tag = strdup(args[1]);
1348 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001349 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1350 if (global.spread_checks != 0) {
1351 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001352 err_code |= ERR_ALERT;
1353 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001354 }
1355 if (*(args[1]) == 0) {
1356 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001357 err_code |= ERR_ALERT | ERR_FATAL;
1358 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001359 }
1360 global.spread_checks = atol(args[1]);
1361 if (global.spread_checks < 0 || global.spread_checks > 50) {
1362 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001366 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1367 const char *err;
1368 unsigned int val;
1369
1370
1371 if (*(args[1]) == 0) {
1372 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1373 err_code |= ERR_ALERT | ERR_FATAL;
1374 goto out;
1375 }
1376
1377 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1378 if (err) {
1379 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1380 err_code |= ERR_ALERT | ERR_FATAL;
1381 }
1382 global.max_spread_checks = val;
1383 if (global.max_spread_checks < 0) {
1384 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1385 err_code |= ERR_ALERT | ERR_FATAL;
1386 }
1387 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001388 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1389#ifdef USE_CPU_AFFINITY
1390 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001391 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001392 unsigned long cpus = 0;
1393
1394 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001395 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001396 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001397 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001398 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001399 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001400 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001401 proc = atol(args[1]);
1402 if (proc >= 1 && proc <= LONGBITS)
1403 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001404 }
1405
1406 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001407 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1408 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001409 err_code |= ERR_ALERT | ERR_FATAL;
1410 goto out;
1411 }
1412
1413 cur_arg = 2;
1414 while (*args[cur_arg]) {
1415 unsigned int low, high;
1416
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001417 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001418 char *dash = strchr(args[cur_arg], '-');
1419
1420 low = high = str2uic(args[cur_arg]);
1421 if (dash)
1422 high = str2uic(dash + 1);
1423
1424 if (high < low) {
1425 unsigned int swap = low;
1426 low = high;
1427 high = swap;
1428 }
1429
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001430 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001431 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001432 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
1435 }
1436
1437 while (low <= high)
1438 cpus |= 1UL << low++;
1439 }
1440 else {
1441 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1442 file, linenum, args[0], args[cur_arg]);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446 cur_arg++;
1447 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001448 for (i = 0; i < LONGBITS; i++)
1449 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001450 global.cpu_map[i] = cpus;
1451#else
1452 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto out;
1455#endif
1456 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001458 struct cfg_kw_list *kwl;
1459 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001460 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001461
1462 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1463 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1464 if (kwl->kw[index].section != CFG_GLOBAL)
1465 continue;
1466 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001467 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001468 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001469 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001470 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001471 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001472 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001473 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001474 err_code |= ERR_WARN;
1475 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001476 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001477 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001478 }
1479 }
1480 }
1481
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001485
Willy Tarreau058e9072009-07-20 09:30:05 +02001486 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001487 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001488 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489}
1490
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001491void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001493 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 defproxy.mode = PR_MODE_TCP;
1495 defproxy.state = PR_STNEW;
1496 defproxy.maxconn = cfg_maxpconn;
1497 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001498
Simon Horman66183002013-02-23 10:16:43 +09001499 defproxy.defsrv.check.inter = DEF_CHKINTR;
1500 defproxy.defsrv.check.fastinter = 0;
1501 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001502 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1503 defproxy.defsrv.agent.fastinter = 0;
1504 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001505 defproxy.defsrv.check.rise = DEF_RISETIME;
1506 defproxy.defsrv.check.fall = DEF_FALLTIME;
1507 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1508 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001509 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001510 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001511 defproxy.defsrv.maxqueue = 0;
1512 defproxy.defsrv.minconn = 0;
1513 defproxy.defsrv.maxconn = 0;
1514 defproxy.defsrv.slowstart = 0;
1515 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1516 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1517 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518}
1519
Willy Tarreauade5ec42010-01-28 19:33:49 +01001520
Willy Tarreau63af98d2014-05-18 08:11:41 +02001521/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1522 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1523 * ERR_FATAL in case of error.
1524 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001525static int create_cond_regex_rule(const char *file, int line,
1526 struct proxy *px, int dir, int action, int flags,
1527 const char *cmd, const char *reg, const char *repl,
1528 const char **cond_start)
1529{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001530 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001531 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001532 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001533 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001534 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001535 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001536 int cs;
1537 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001538
1539 if (px == &defproxy) {
1540 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001541 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001542 goto err;
1543 }
1544
1545 if (*reg == 0) {
1546 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001547 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001548 goto err;
1549 }
1550
1551 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001552 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001553
Willy Tarreau5321c422010-01-28 20:35:13 +01001554 if (cond_start &&
1555 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001556 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1557 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1558 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001559 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001560 goto err;
1561 }
1562 }
1563 else if (cond_start && **cond_start) {
1564 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1565 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001566 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001567 goto err;
1568 }
1569
Willy Tarreau63af98d2014-05-18 08:11:41 +02001570 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001571 (dir == SMP_OPT_DIR_REQ) ?
1572 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1573 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1574 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001575
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001576 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001577 if (!preg) {
1578 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001579 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001580 goto err;
1581 }
1582
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001583 cs = !(flags & REG_ICASE);
1584 cap = !(flags & REG_NOSUB);
1585 error = NULL;
1586 if (!regex_comp(reg, preg, cs, cap, &error)) {
1587 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1588 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001589 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001590 goto err;
1591 }
1592
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001593 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001594 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001595 if (repl && err) {
1596 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1597 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001598 ret_code |= ERR_ALERT | ERR_FATAL;
1599 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001600 }
1601
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001602 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001603 ret_code |= ERR_WARN;
1604
1605 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001606
Willy Tarreau63af98d2014-05-18 08:11:41 +02001607 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001608 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001609 err:
1610 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001611 free(errmsg);
1612 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001613}
1614
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001616 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001617 * Returns the error code, 0 if OK, or any combination of :
1618 * - ERR_ABORT: must abort ASAP
1619 * - ERR_FATAL: we can continue parsing but not start the service
1620 * - ERR_WARN: a warning has been emitted
1621 * - ERR_ALERT: an alert has been emitted
1622 * Only the two first ones can stop processing, the two others are just
1623 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001625int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1626{
1627 static struct peers *curpeers = NULL;
1628 struct peer *newpeer = NULL;
1629 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001630 struct bind_conf *bind_conf;
1631 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001632 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001633 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001634
1635 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001636 if (!*args[1]) {
1637 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001638 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001639 goto out;
1640 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001641
1642 err = invalid_char(args[1]);
1643 if (err) {
1644 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1645 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001646 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001647 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001648 }
1649
1650 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1651 /*
1652 * If there are two proxies with the same name only following
1653 * combinations are allowed:
1654 */
1655 if (strcmp(curpeers->id, args[1]) == 0) {
1656 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1657 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1658 err_code |= ERR_WARN;
1659 }
1660 }
1661
1662 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1663 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1664 err_code |= ERR_ALERT | ERR_ABORT;
1665 goto out;
1666 }
1667
1668 curpeers->next = peers;
1669 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001670 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001671 curpeers->conf.line = linenum;
1672 curpeers->last_change = now.tv_sec;
1673 curpeers->id = strdup(args[1]);
1674 }
1675 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001676 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001677 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001678 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001679
1680 if (!*args[2]) {
1681 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1682 file, linenum, args[0]);
1683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
1685 }
1686
1687 err = invalid_char(args[1]);
1688 if (err) {
1689 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1690 file, linenum, *err, args[1]);
1691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
1693 }
1694
1695 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1696 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1697 err_code |= ERR_ALERT | ERR_ABORT;
1698 goto out;
1699 }
1700
1701 /* the peers are linked backwards first */
1702 curpeers->count++;
1703 newpeer->next = curpeers->remote;
1704 curpeers->remote = newpeer;
1705 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001706 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001707 newpeer->conf.line = linenum;
1708
1709 newpeer->last_change = now.tv_sec;
1710 newpeer->id = strdup(args[1]);
1711
Willy Tarreau902636f2013-03-10 19:44:48 +01001712 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001713 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001714 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001717 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001718
1719 proto = protocol_by_family(sk->ss_family);
1720 if (!proto || !proto->connect) {
1721 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1722 file, linenum, args[0], args[1]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001726
1727 if (port1 != port2) {
1728 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1729 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
1732 }
1733
Willy Tarreau2aa38802013-02-20 19:20:59 +01001734 if (!port1) {
1735 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1736 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
1739 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001740
Emeric Brun32da3c42010-09-23 18:39:19 +02001741 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001742 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001743 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001744 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001745
Emeric Brun32da3c42010-09-23 18:39:19 +02001746 if (strcmp(newpeer->id, localpeer) == 0) {
1747 /* Current is local peer, it define a frontend */
1748 newpeer->local = 1;
1749
1750 if (!curpeers->peers_fe) {
1751 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1752 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1753 err_code |= ERR_ALERT | ERR_ABORT;
1754 goto out;
1755 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001756
Willy Tarreau237250c2011-07-29 01:49:03 +02001757 init_new_proxy(curpeers->peers_fe);
1758 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001759
1760 curpeers->peers_fe->last_change = now.tv_sec;
1761 curpeers->peers_fe->id = strdup(args[1]);
1762 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001763 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001764 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1765 curpeers->peers_fe->timeout.connect = 5000;
1766 curpeers->peers_fe->accept = peer_accept;
1767 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001768 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1769 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001770
1771 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1772
Willy Tarreau902636f2013-03-10 19:44:48 +01001773 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1774 if (errmsg && *errmsg) {
1775 indent_msg(&errmsg, 2);
1776 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001777 }
1778 else
1779 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1780 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001781 err_code |= ERR_FATAL;
1782 goto out;
1783 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001784
1785 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001786 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001787 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1788 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1789 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1790 l->accept = session_accept;
1791 l->handler = process_session;
1792 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1793 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1794 global.maxsock += l->maxconn;
1795 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001796 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001797 else {
1798 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1799 file, linenum, args[0], args[1],
1800 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1801 err_code |= ERR_FATAL;
1802 goto out;
1803 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001804 }
1805 } /* neither "peer" nor "peers" */
1806 else if (*args[0] != 0) {
1807 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001813 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001814 return err_code;
1815}
1816
Willy Tarreau3842f002009-06-14 11:39:52 +02001817int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818{
1819 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001820 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001821 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001822 int rc;
1823 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001824 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001825 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001826 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001827 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001828 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 if (!strcmp(args[0], "listen"))
1831 rc = PR_CAP_LISTEN;
1832 else if (!strcmp(args[0], "frontend"))
1833 rc = PR_CAP_FE | PR_CAP_RS;
1834 else if (!strcmp(args[0], "backend"))
1835 rc = PR_CAP_BE | PR_CAP_RS;
1836 else if (!strcmp(args[0], "ruleset"))
1837 rc = PR_CAP_RS;
1838 else
1839 rc = PR_CAP_NONE;
1840
1841 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001842 struct ebpt_node *node;
1843
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 if (!*args[1]) {
1845 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1846 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1847 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_ALERT | ERR_ABORT;
1849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001851
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001852 err = invalid_char(args[1]);
1853 if (err) {
1854 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1855 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001857 }
1858
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001859 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1860 curproxy = container_of(node, struct proxy, conf.by_name);
1861
1862 if (strcmp(curproxy->id, args[1]) != 0)
1863 break;
1864
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001865 /*
1866 * If there are two proxies with the same name only following
1867 * combinations are allowed:
1868 *
1869 * listen backend frontend ruleset
1870 * listen - - - -
1871 * backend - - OK -
1872 * frontend - OK - -
1873 * ruleset - - - -
1874 */
1875
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001876 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1877 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001878 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1879 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1880 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001881 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001882 }
1883 }
1884
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1886 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_ABORT;
1888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001890
Willy Tarreau97cb7802010-01-03 20:23:58 +01001891 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 curproxy->next = proxy;
1893 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001894 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1895 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001896 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001898 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001899 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900
1901 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001903 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001904
Willy Tarreau4348fad2012-09-20 16:48:07 +02001905 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1906
Willy Tarreau902636f2013-03-10 19:44:48 +01001907 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1908 if (errmsg && *errmsg) {
1909 indent_msg(&errmsg, 2);
1910 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001911 }
1912 else
1913 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1914 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_FATAL;
1916 goto out;
1917 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001918
Willy Tarreau4348fad2012-09-20 16:48:07 +02001919 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001920 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001921 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 }
1923
1924 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001925 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001926 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001927
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001930 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001931 curproxy->no_options = defproxy.no_options;
1932 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001933 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001934 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001935 curproxy->except_net = defproxy.except_net;
1936 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001937 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001938 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001940 if (defproxy.fwdfor_hdr_len) {
1941 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1942 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1943 }
1944
Willy Tarreaub86db342009-11-30 11:50:16 +01001945 if (defproxy.orgto_hdr_len) {
1946 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1947 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1948 }
1949
Mark Lamourinec2247f02012-01-04 13:02:01 -05001950 if (defproxy.server_id_hdr_len) {
1951 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1952 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1953 }
1954
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955 if (curproxy->cap & PR_CAP_FE) {
1956 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001957 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001958 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959
1960 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001961 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1962 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001963
1964 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966
Willy Tarreau977b8e42006-12-29 14:19:17 +01001967 if (curproxy->cap & PR_CAP_BE) {
1968 curproxy->fullconn = defproxy.fullconn;
1969 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001970 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001972 if (defproxy.check_req) {
1973 curproxy->check_req = calloc(1, defproxy.check_len);
1974 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1975 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001976 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001978 if (defproxy.expect_str) {
1979 curproxy->expect_str = strdup(defproxy.expect_str);
1980 if (defproxy.expect_regex) {
1981 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001982 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
1983 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001984 }
1985 }
1986
Willy Tarreau67402132012-05-31 20:40:20 +02001987 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988 if (defproxy.cookie_name)
1989 curproxy->cookie_name = strdup(defproxy.cookie_name);
1990 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001991 if (defproxy.cookie_domain)
1992 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001993
Willy Tarreau31936852010-10-06 16:59:56 +02001994 if (defproxy.cookie_maxidle)
1995 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1996
1997 if (defproxy.cookie_maxlife)
1998 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1999
Emeric Brun647caf12009-06-30 17:57:00 +02002000 if (defproxy.rdp_cookie_name)
2001 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2002 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2003
Willy Tarreau01732802007-11-01 22:48:15 +01002004 if (defproxy.url_param_name)
2005 curproxy->url_param_name = strdup(defproxy.url_param_name);
2006 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002007
Benoitaffb4812009-03-25 13:02:10 +01002008 if (defproxy.hh_name)
2009 curproxy->hh_name = strdup(defproxy.hh_name);
2010 curproxy->hh_len = defproxy.hh_len;
2011 curproxy->hh_match_domain = defproxy.hh_match_domain;
2012
Willy Tarreauef9a3602012-12-08 22:29:20 +01002013 if (defproxy.conn_src.iface_name)
2014 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2015 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002016 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002017#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002018 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002019#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002022 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002023 if (defproxy.capture_name)
2024 curproxy->capture_name = strdup(defproxy.capture_name);
2025 curproxy->capture_namelen = defproxy.capture_namelen;
2026 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028
Willy Tarreau977b8e42006-12-29 14:19:17 +01002029 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002030 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002031 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002032 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002033 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002034 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035 curproxy->mon_net = defproxy.mon_net;
2036 curproxy->mon_mask = defproxy.mon_mask;
2037 if (defproxy.monitor_uri)
2038 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2039 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002040 if (defproxy.defbe.name)
2041 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002042
2043 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002044 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2045 if (curproxy->conf.logformat_string &&
2046 curproxy->conf.logformat_string != default_http_log_format &&
2047 curproxy->conf.logformat_string != default_tcp_log_format &&
2048 curproxy->conf.logformat_string != clf_http_log_format)
2049 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2050
2051 if (defproxy.conf.lfs_file) {
2052 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2053 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2054 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002055 }
2056
2057 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002058 curproxy->timeout.connect = defproxy.timeout.connect;
2059 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002060 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002061 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002062 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002063 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002064 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002065 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002066 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002067 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 }
2069
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002071 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002072
2073 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002074 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002075 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002076 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002077 LIST_INIT(&node->list);
2078 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2079 }
2080
Willy Tarreau62a61232013-04-12 18:13:46 +02002081 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2082 if (curproxy->conf.uniqueid_format_string)
2083 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2084
2085 if (defproxy.conf.uif_file) {
2086 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2087 curproxy->conf.uif_line = defproxy.conf.uif_line;
2088 }
William Lallemanda73203e2012-03-12 12:48:57 +01002089
2090 /* copy default header unique id */
2091 if (defproxy.header_unique_id)
2092 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2093
William Lallemand82fe75c2012-10-23 10:25:10 +02002094 /* default compression options */
2095 if (defproxy.comp != NULL) {
2096 curproxy->comp = calloc(1, sizeof(struct comp));
2097 curproxy->comp->algos = defproxy.comp->algos;
2098 curproxy->comp->types = defproxy.comp->types;
2099 }
2100
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002102 curproxy->conf.used_listener_id = EB_ROOT;
2103 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002104
Willy Tarreau93893792009-07-23 13:19:11 +02002105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
2107 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2108 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002109 /* FIXME-20070101: we should do this too at the end of the
2110 * config parsing to free all default values.
2111 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002112 free(defproxy.check_req);
2113 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002114 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002115 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002116 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002117 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002118 free(defproxy.capture_name);
2119 free(defproxy.monitor_uri);
2120 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002121 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002122 free(defproxy.fwdfor_hdr_name);
2123 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002124 free(defproxy.orgto_hdr_name);
2125 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002126 free(defproxy.server_id_hdr_name);
2127 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002128 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002129 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002130 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002131 free(defproxy.expect_regex);
2132 defproxy.expect_regex = NULL;
2133 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002134
Willy Tarreau62a61232013-04-12 18:13:46 +02002135 if (defproxy.conf.logformat_string != default_http_log_format &&
2136 defproxy.conf.logformat_string != default_tcp_log_format &&
2137 defproxy.conf.logformat_string != clf_http_log_format)
2138 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002139
Willy Tarreau62a61232013-04-12 18:13:46 +02002140 free(defproxy.conf.uniqueid_format_string);
2141 free(defproxy.conf.lfs_file);
2142 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002143
Willy Tarreaua534fea2008-08-03 12:19:50 +02002144 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002145 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002146
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 /* we cannot free uri_auth because it might already be used */
2148 init_default_instance();
2149 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002150 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2151 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154 }
2155 else if (curproxy == NULL) {
2156 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002160
2161 /* update the current file and line being parsed */
2162 curproxy->conf.args.file = curproxy->conf.file;
2163 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002164
2165 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002166 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2167 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2168 if (err_code & ERR_FATAL)
2169 goto out;
2170 }
2171 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002172 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002173 int cur_arg;
2174
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175 if (curproxy == &defproxy) {
2176 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002179 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002180 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002181 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182
Willy Tarreau24709282013-03-10 21:32:12 +01002183 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002184 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002189
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002190 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002191
2192 /* use default settings for unix sockets */
2193 bind_conf->ux.uid = global.unix_bind.ux.uid;
2194 bind_conf->ux.gid = global.unix_bind.ux.gid;
2195 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002196
2197 /* NOTE: the following line might create several listeners if there
2198 * are comma-separated IPs or port ranges. So all further processing
2199 * will have to be applied to all listeners created after last_listen.
2200 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002201 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2202 if (errmsg && *errmsg) {
2203 indent_msg(&errmsg, 2);
2204 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002205 }
2206 else
2207 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2208 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
2211 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002212
Willy Tarreau4348fad2012-09-20 16:48:07 +02002213 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2214 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002215 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002216 }
2217
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002218 cur_arg = 2;
2219 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002220 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002221 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002222 char *err;
2223
Willy Tarreau26982662012-09-12 23:17:10 +02002224 kw = bind_find_kw(args[cur_arg]);
2225 if (kw) {
2226 char *err = NULL;
2227 int code;
2228
2229 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002230 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2231 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002232 cur_arg += 1 + kw->skip ;
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236
Willy Tarreau4348fad2012-09-20 16:48:07 +02002237 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002238 err_code |= code;
2239
2240 if (code) {
2241 if (err && *err) {
2242 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002243 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002244 }
2245 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002246 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2247 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002248 if (code & ERR_FATAL) {
2249 free(err);
2250 cur_arg += 1 + kw->skip;
2251 goto out;
2252 }
2253 }
2254 free(err);
2255 cur_arg += 1 + kw->skip;
2256 continue;
2257 }
2258
Willy Tarreau8638f482012-09-18 18:01:17 +02002259 err = NULL;
2260 if (!bind_dumped) {
2261 bind_dump_kws(&err);
2262 indent_msg(&err, 4);
2263 bind_dumped = 1;
2264 }
2265
2266 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2267 file, linenum, args[0], args[1], args[cur_arg],
2268 err ? " Registered keywords :" : "", err ? err : "");
2269 free(err);
2270
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002273 }
Willy Tarreau93893792009-07-23 13:19:11 +02002274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 }
2276 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002277 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2279 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002283 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002285
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 /* flush useless bits */
2287 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002290 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293
Willy Tarreau1c47f852006-07-09 08:22:27 +02002294 if (!*args[1]) {
2295 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2296 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002297 err_code |= ERR_ALERT | ERR_FATAL;
2298 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002299 }
2300
Willy Tarreaua534fea2008-08-03 12:19:50 +02002301 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002302 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002303 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002304 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002305 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2306
Willy Tarreau93893792009-07-23 13:19:11 +02002307 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2310 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2311 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2312 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2313 else {
2314 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 }
2318 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002319 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002320 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002321
2322 if (curproxy == &defproxy) {
2323 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2324 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002327 }
2328
2329 if (!*args[1]) {
2330 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2331 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002334 }
2335
2336 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002337 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002338
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002339 if (curproxy->uuid <= 0) {
2340 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002341 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002344 }
2345
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002346 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2347 if (node) {
2348 struct proxy *target = container_of(node, struct proxy, conf.id);
2349 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2350 file, linenum, proxy_type_str(curproxy), curproxy->id,
2351 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
2354 }
2355 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002356 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002357 else if (!strcmp(args[0], "description")) {
2358 int i, len=0;
2359 char *d;
2360
Cyril Bonté99ed3272010-01-24 23:29:44 +01002361 if (curproxy == &defproxy) {
2362 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2363 file, linenum, args[0]);
2364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
2366 }
2367
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002368 if (!*args[1]) {
2369 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2370 file, linenum, args[0]);
2371 return -1;
2372 }
2373
Willy Tarreau348acfe2014-04-14 15:00:39 +02002374 for (i = 1; *args[i]; i++)
2375 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002376
2377 d = (char *)calloc(1, len);
2378 curproxy->desc = d;
2379
Willy Tarreau348acfe2014-04-14 15:00:39 +02002380 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2381 for (i = 2; *args[i]; i++)
2382 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002383
2384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2386 curproxy->state = PR_STSTOPPED;
2387 }
2388 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2389 curproxy->state = PR_STNEW;
2390 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002391 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2392 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002393 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002394
2395 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002396 unsigned int low, high;
2397
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002398 if (strcmp(args[cur_arg], "all") == 0) {
2399 set = 0;
2400 break;
2401 }
2402 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002403 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002404 }
2405 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002406 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002407 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002408 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002409 char *dash = strchr(args[cur_arg], '-');
2410
2411 low = high = str2uic(args[cur_arg]);
2412 if (dash)
2413 high = str2uic(dash + 1);
2414
2415 if (high < low) {
2416 unsigned int swap = low;
2417 low = high;
2418 high = swap;
2419 }
2420
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002421 if (low < 1 || high > LONGBITS) {
2422 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2423 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002426 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002427 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002428 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002429 }
2430 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002431 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2432 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002435 }
2436 cur_arg++;
2437 }
2438 curproxy->bind_proc = set;
2439 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002440 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002441 if (curproxy == &defproxy) {
2442 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002445 }
2446
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002447 err = invalid_char(args[1]);
2448 if (err) {
2449 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2450 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002452 }
2453
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002454 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002455 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2456 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002459 }
2460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2462 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463
Willy Tarreau977b8e42006-12-29 14:19:17 +01002464 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002466
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 if (*(args[1]) == 0) {
2468 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2469 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002473
Willy Tarreau67402132012-05-31 20:40:20 +02002474 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002475 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002476 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002477 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 curproxy->cookie_name = strdup(args[1]);
2479 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002480
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 cur_arg = 2;
2482 while (*(args[cur_arg])) {
2483 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002484 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
2486 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002487 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 }
2489 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002490 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 }
2492 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002493 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 }
2495 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002496 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002498 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002499 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002502 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002504 else if (!strcmp(args[cur_arg], "httponly")) {
2505 curproxy->ck_opts |= PR_CK_HTTPONLY;
2506 }
2507 else if (!strcmp(args[cur_arg], "secure")) {
2508 curproxy->ck_opts |= PR_CK_SECURE;
2509 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002510 else if (!strcmp(args[cur_arg], "domain")) {
2511 if (!*args[cur_arg + 1]) {
2512 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2513 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002516 }
2517
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002518 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002519 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002520 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2521 " dots nor does not start with a dot."
2522 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002523 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002524 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002525 }
2526
2527 err = invalid_domainchar(args[cur_arg + 1]);
2528 if (err) {
2529 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2530 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002533 }
2534
Willy Tarreau68a897b2009-12-03 23:28:34 +01002535 if (!curproxy->cookie_domain) {
2536 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2537 } else {
2538 /* one domain was already specified, add another one by
2539 * building the string which will be returned along with
2540 * the cookie.
2541 */
2542 char *new_ptr;
2543 int new_len = strlen(curproxy->cookie_domain) +
2544 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2545 new_ptr = malloc(new_len);
2546 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2547 free(curproxy->cookie_domain);
2548 curproxy->cookie_domain = new_ptr;
2549 }
Willy Tarreau31936852010-10-06 16:59:56 +02002550 cur_arg++;
2551 }
2552 else if (!strcmp(args[cur_arg], "maxidle")) {
2553 unsigned int maxidle;
2554 const char *res;
2555
2556 if (!*args[cur_arg + 1]) {
2557 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2558 file, linenum, args[cur_arg]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562
2563 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2564 if (res) {
2565 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2566 file, linenum, *res, args[cur_arg]);
2567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
2569 }
2570 curproxy->cookie_maxidle = maxidle;
2571 cur_arg++;
2572 }
2573 else if (!strcmp(args[cur_arg], "maxlife")) {
2574 unsigned int maxlife;
2575 const char *res;
2576
2577 if (!*args[cur_arg + 1]) {
2578 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2579 file, linenum, args[cur_arg]);
2580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
2582 }
2583
2584 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2585 if (res) {
2586 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2587 file, linenum, *res, args[cur_arg]);
2588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
2590 }
2591 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002592 cur_arg++;
2593 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002595 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 +02002596 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 }
2600 cur_arg++;
2601 }
Willy Tarreau67402132012-05-31 20:40:20 +02002602 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2604 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 }
2607
Willy Tarreau67402132012-05-31 20:40:20 +02002608 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2610 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002613
Willy Tarreau67402132012-05-31 20:40:20 +02002614 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002615 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2616 file, linenum);
2617 err_code |= ERR_ALERT | ERR_FATAL;
2618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002620 else if (!strcmp(args[0], "persist")) { /* persist */
2621 if (*(args[1]) == 0) {
2622 Alert("parsing [%s:%d] : missing persist method.\n",
2623 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002626 }
2627
2628 if (!strncmp(args[1], "rdp-cookie", 10)) {
2629 curproxy->options2 |= PR_O2_RDPC_PRST;
2630
Emeric Brunb982a3d2010-01-04 15:45:53 +01002631 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002632 const char *beg, *end;
2633
2634 beg = args[1] + 11;
2635 end = strchr(beg, ')');
2636
2637 if (!end || end == beg) {
2638 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2639 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002642 }
2643
2644 free(curproxy->rdp_cookie_name);
2645 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2646 curproxy->rdp_cookie_len = end-beg;
2647 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002648 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002649 free(curproxy->rdp_cookie_name);
2650 curproxy->rdp_cookie_name = strdup("msts");
2651 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2652 }
2653 else { /* syntax */
2654 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2655 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002658 }
2659 }
2660 else {
2661 Alert("parsing [%s:%d] : unknown persist method.\n",
2662 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002665 }
2666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002668 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002670 if (curproxy == &defproxy) {
2671 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002680 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
2685 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002686 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 curproxy->appsession_name = strdup(args[1]);
2688 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2689 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002690 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2691 if (err) {
2692 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2693 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002696 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002697 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002698
Willy Tarreau51041c72007-09-09 21:56:53 +02002699 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2700 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_ALERT | ERR_ABORT;
2702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002704
2705 cur_arg = 6;
2706 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002707 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2708 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002709 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002710 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002711 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002712 } else if (!strcmp(args[cur_arg], "prefix")) {
2713 curproxy->options2 |= PR_O2_AS_PFX;
2714 } else if (!strcmp(args[cur_arg], "mode")) {
2715 if (!*args[cur_arg + 1]) {
2716 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2717 file, linenum, args[0], args[cur_arg]);
2718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
2720 }
2721
2722 cur_arg++;
2723 if (!strcmp(args[cur_arg], "query-string")) {
2724 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2725 curproxy->options2 |= PR_O2_AS_M_QS;
2726 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2727 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2728 curproxy->options2 |= PR_O2_AS_M_PP;
2729 } else {
2730 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
2733 }
2734 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002735 cur_arg++;
2736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 } /* Url App Session */
2738 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002739 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002743 if (curproxy == &defproxy) {
2744 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 if (*(args[4]) == 0) {
2750 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2751 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002755 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->capture_name = strdup(args[2]);
2757 curproxy->capture_namelen = strlen(curproxy->capture_name);
2758 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 curproxy->to_log |= LW_COOKIE;
2760 }
2761 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2762 struct cap_hdr *hdr;
2763
2764 if (curproxy == &defproxy) {
2765 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 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 }
2769
2770 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2771 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2772 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
2776
2777 hdr = calloc(sizeof(struct cap_hdr), 1);
2778 hdr->next = curproxy->req_cap;
2779 hdr->name = strdup(args[3]);
2780 hdr->namelen = strlen(args[3]);
2781 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002782 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 hdr->index = curproxy->nb_req_cap++;
2784 curproxy->req_cap = hdr;
2785 curproxy->to_log |= LW_REQHDR;
2786 }
2787 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2788 struct cap_hdr *hdr;
2789
2790 if (curproxy == &defproxy) {
2791 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 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 }
2795
2796 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2797 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2798 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 }
2802 hdr = calloc(sizeof(struct cap_hdr), 1);
2803 hdr->next = curproxy->rsp_cap;
2804 hdr->name = strdup(args[3]);
2805 hdr->namelen = strlen(args[3]);
2806 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002807 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 hdr->index = curproxy->nb_rsp_cap++;
2809 curproxy->rsp_cap = hdr;
2810 curproxy->to_log |= LW_RSPHDR;
2811 }
2812 else {
2813 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2814 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817 }
2818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002821 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002822
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 if (*(args[1]) == 0) {
2824 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2825 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 }
2829 curproxy->conn_retries = atol(args[1]);
2830 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002831 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002832 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002833
2834 if (curproxy == &defproxy) {
2835 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839
Willy Tarreau20b0de52012-12-24 15:45:22 +01002840 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2841 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2842 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2843 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002844 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002845 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2846 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 +01002847 file, linenum, args[0]);
2848 err_code |= ERR_WARN;
2849 }
2850
Willy Tarreauff011f22011-01-06 17:51:27 +01002851 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002852
Willy Tarreauff011f22011-01-06 17:51:27 +01002853 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002854 err_code |= ERR_ALERT | ERR_ABORT;
2855 goto out;
2856 }
2857
Willy Tarreau5002f572014-04-23 01:32:02 +02002858 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002859 err_code |= warnif_cond_conflicts(rule->cond,
2860 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2861 file, linenum);
2862
Willy Tarreauff011f22011-01-06 17:51:27 +01002863 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002864 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002865 else if (!strcmp(args[0], "http-response")) { /* response access control */
2866 struct http_res_rule *rule;
2867
2868 if (curproxy == &defproxy) {
2869 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873
2874 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2875 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2876 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2877 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2878 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2879 file, linenum, args[0]);
2880 err_code |= ERR_WARN;
2881 }
2882
2883 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2884
2885 if (!rule) {
2886 err_code |= ERR_ALERT | ERR_ABORT;
2887 goto out;
2888 }
2889
2890 err_code |= warnif_cond_conflicts(rule->cond,
2891 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2892 file, linenum);
2893
2894 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2895 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002896 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2897 /* set the header name and length into the proxy structure */
2898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2899 err_code |= ERR_WARN;
2900
2901 if (!*args[1]) {
2902 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2903 file, linenum, args[0]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907
2908 /* set the desired header name */
2909 free(curproxy->server_id_hdr_name);
2910 curproxy->server_id_hdr_name = strdup(args[1]);
2911 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2912 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002913 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002914 struct http_req_rule *rule;
2915
Willy Tarreaub099aca2008-10-12 17:26:37 +02002916 if (curproxy == &defproxy) {
2917 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002920 }
2921
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002922 /* emulate "block" using "http-request block". Since these rules are supposed to
2923 * be processed before all http-request rules, we put them into their own list
2924 * and will insert them at the end.
2925 */
2926 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2927 if (!rule) {
2928 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002929 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002930 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002931 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2932 err_code |= warnif_cond_conflicts(rule->cond,
2933 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2934 file, linenum);
2935 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002936
2937 if (!already_warned(WARN_BLOCK_DEPRECATED))
2938 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of 'http-request deny' which uses the exact same syntax. The rules are translated but support might disappear in a future version.\n", file, linenum, args[0]);
2939
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002940 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002941 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002942 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002943
Cyril Bonté99ed3272010-01-24 23:29:44 +01002944 if (curproxy == &defproxy) {
2945 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2946 err_code |= ERR_ALERT | ERR_FATAL;
2947 goto out;
2948 }
2949
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002950 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002951 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2952 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002955 }
2956
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002957 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002958 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002959 err_code |= warnif_cond_conflicts(rule->cond,
2960 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2961 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002962 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002963 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002964 struct switching_rule *rule;
2965
Willy Tarreaub099aca2008-10-12 17:26:37 +02002966 if (curproxy == &defproxy) {
2967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002970 }
2971
Willy Tarreau55ea7572007-06-17 19:56:27 +02002972 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002973 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002974
2975 if (*(args[1]) == 0) {
2976 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002979 }
2980
Willy Tarreauf51658d2014-04-23 01:21:56 +02002981 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2982 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2983 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2984 file, linenum, errmsg);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002988
Willy Tarreauf51658d2014-04-23 01:21:56 +02002989 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002990 }
2991
2992 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2993 rule->cond = cond;
2994 rule->be.name = strdup(args[1]);
2995 LIST_INIT(&rule->list);
2996 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2997 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002998 else if (strcmp(args[0], "use-server") == 0) {
2999 struct server_rule *rule;
3000
3001 if (curproxy == &defproxy) {
3002 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
3007 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3008 err_code |= ERR_WARN;
3009
3010 if (*(args[1]) == 0) {
3011 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
3014 }
3015
3016 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3017 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3018 file, linenum, args[0]);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
3022
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003023 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3024 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3025 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003030 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003031
3032 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3033 rule->cond = cond;
3034 rule->srv.name = strdup(args[1]);
3035 LIST_INIT(&rule->list);
3036 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3037 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3038 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003039 else if ((!strcmp(args[0], "force-persist")) ||
3040 (!strcmp(args[0], "ignore-persist"))) {
3041 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003042
3043 if (curproxy == &defproxy) {
3044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
3047 }
3048
3049 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3050 err_code |= ERR_WARN;
3051
Willy Tarreauef6494c2010-01-28 17:12:36 +01003052 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003053 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3054 file, linenum, args[0]);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003059 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3060 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3061 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003066 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3067 * where force-persist is applied.
3068 */
3069 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003070
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003071 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003072 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003073 if (!strcmp(args[0], "force-persist")) {
3074 rule->type = PERSIST_TYPE_FORCE;
3075 } else {
3076 rule->type = PERSIST_TYPE_IGNORE;
3077 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003078 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003079 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003080 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003081 else if (!strcmp(args[0], "stick-table")) {
3082 int myidx = 1;
3083
Emeric Brun32da3c42010-09-23 18:39:19 +02003084 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003085 curproxy->table.type = (unsigned int)-1;
3086 while (*args[myidx]) {
3087 const char *err;
3088
3089 if (strcmp(args[myidx], "size") == 0) {
3090 myidx++;
3091 if (!*(args[myidx])) {
3092 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3093 file, linenum, args[myidx-1]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3098 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3099 file, linenum, *err, args[myidx-1]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003103 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003104 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003105 else if (strcmp(args[myidx], "peers") == 0) {
3106 myidx++;
Godbach50523162013-12-11 19:48:57 +08003107 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003108 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3109 file, linenum, args[myidx-1]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
Godbach50523162013-12-11 19:48:57 +08003112 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003113 curproxy->table.peers.name = strdup(args[myidx++]);
3114 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003115 else if (strcmp(args[myidx], "expire") == 0) {
3116 myidx++;
3117 if (!*(args[myidx])) {
3118 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3119 file, linenum, args[myidx-1]);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3124 if (err) {
3125 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3126 file, linenum, *err, args[myidx-1]);
3127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003131 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003132 }
3133 else if (strcmp(args[myidx], "nopurge") == 0) {
3134 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003135 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003136 }
3137 else if (strcmp(args[myidx], "type") == 0) {
3138 myidx++;
3139 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3140 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3141 file, linenum, args[myidx]);
3142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003145 /* myidx already points to next arg */
3146 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003147 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003148 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003149 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003150
3151 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003152 nw = args[myidx];
3153 while (*nw) {
3154 /* the "store" keyword supports a comma-separated list */
3155 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003156 sa = NULL; /* store arg */
3157 while (*nw && *nw != ',') {
3158 if (*nw == '(') {
3159 *nw = 0;
3160 sa = ++nw;
3161 while (*nw != ')') {
3162 if (!*nw) {
3163 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3164 file, linenum, args[0], cw);
3165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167 }
3168 nw++;
3169 }
3170 *nw = '\0';
3171 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003172 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003173 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003174 if (*nw)
3175 *nw++ = '\0';
3176 type = stktable_get_data_type(cw);
3177 if (type < 0) {
3178 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3179 file, linenum, args[0], cw);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
Willy Tarreauac782882010-06-20 10:41:54 +02003183
3184 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3185 switch (err) {
3186 case PE_NONE: break;
3187 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003188 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3189 file, linenum, args[0], cw);
3190 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003191 break;
3192
3193 case PE_ARG_MISSING:
3194 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3195 file, linenum, args[0], cw);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198
3199 case PE_ARG_NOT_USED:
3200 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3201 file, linenum, args[0], cw);
3202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
3204
3205 default:
3206 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3207 file, linenum, args[0], cw);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003210 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003211 }
3212 myidx++;
3213 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003214 else {
3215 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3216 file, linenum, args[myidx]);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003219 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003220 }
3221
3222 if (!curproxy->table.size) {
3223 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3224 file, linenum);
3225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
3227 }
3228
3229 if (curproxy->table.type == (unsigned int)-1) {
3230 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3231 file, linenum);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
3234 }
3235 }
3236 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003237 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003238 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003239 int myidx = 0;
3240 const char *name = NULL;
3241 int flags;
3242
3243 if (curproxy == &defproxy) {
3244 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248
3249 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3250 err_code |= ERR_WARN;
3251 goto out;
3252 }
3253
3254 myidx++;
3255 if ((strcmp(args[myidx], "store") == 0) ||
3256 (strcmp(args[myidx], "store-request") == 0)) {
3257 myidx++;
3258 flags = STK_IS_STORE;
3259 }
3260 else if (strcmp(args[myidx], "store-response") == 0) {
3261 myidx++;
3262 flags = STK_IS_STORE | STK_ON_RSP;
3263 }
3264 else if (strcmp(args[myidx], "match") == 0) {
3265 myidx++;
3266 flags = STK_IS_MATCH;
3267 }
3268 else if (strcmp(args[myidx], "on") == 0) {
3269 myidx++;
3270 flags = STK_IS_MATCH | STK_IS_STORE;
3271 }
3272 else {
3273 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
3276 }
3277
3278 if (*(args[myidx]) == 0) {
3279 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
3282 }
3283
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003284 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003285 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003286 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003287 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
3290 }
3291
3292 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003293 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3294 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3295 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003296 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003297 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003298 goto out;
3299 }
3300 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003301 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3302 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3303 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003304 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003305 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003306 goto out;
3307 }
3308 }
3309
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003310 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003311 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003312
Emeric Brunb982a3d2010-01-04 15:45:53 +01003313 if (strcmp(args[myidx], "table") == 0) {
3314 myidx++;
3315 name = args[myidx++];
3316 }
3317
Willy Tarreauef6494c2010-01-28 17:12:36 +01003318 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003319 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3320 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3321 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003322 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003323 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003324 goto out;
3325 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003326 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003327 else if (*(args[myidx])) {
3328 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3329 file, linenum, args[0], args[myidx]);
3330 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003331 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003332 goto out;
3333 }
Emeric Brun97679e72010-09-23 17:56:44 +02003334 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003335 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003336 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003337 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003338
Emeric Brunb982a3d2010-01-04 15:45:53 +01003339 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3340 rule->cond = cond;
3341 rule->expr = expr;
3342 rule->flags = flags;
3343 rule->table.name = name ? strdup(name) : NULL;
3344 LIST_INIT(&rule->list);
3345 if (flags & STK_ON_RSP)
3346 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3347 else
3348 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 else if (!strcmp(args[0], "stats")) {
3351 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3352 curproxy->uri_auth = NULL; /* we must detach from the default config */
3353
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003354 if (!*args[1]) {
3355 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003356 } else if (!strcmp(args[1], "admin")) {
3357 struct stats_admin_rule *rule;
3358
3359 if (curproxy == &defproxy) {
3360 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
3363 }
3364
3365 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3366 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3367 err_code |= ERR_ALERT | ERR_ABORT;
3368 goto out;
3369 }
3370
3371 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3372 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3373 file, linenum, args[0], args[1]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003377 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3378 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3379 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003384 err_code |= warnif_cond_conflicts(cond,
3385 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3386 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003387
3388 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3389 rule->cond = cond;
3390 LIST_INIT(&rule->list);
3391 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 } else if (!strcmp(args[1], "uri")) {
3393 if (*(args[2]) == 0) {
3394 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3398 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_ABORT;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
3402 } else if (!strcmp(args[1], "realm")) {
3403 if (*(args[2]) == 0) {
3404 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_ALERT | ERR_ABORT;
3410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003412 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003413 unsigned interval;
3414
3415 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3416 if (err) {
3417 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3418 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003421 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3422 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_ABORT;
3424 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003425 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003426 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003427 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003428
3429 if (curproxy == &defproxy) {
3430 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
3433 }
3434
3435 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3436 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3437 err_code |= ERR_ALERT | ERR_ABORT;
3438 goto out;
3439 }
3440
Willy Tarreauff011f22011-01-06 17:51:27 +01003441 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3442 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003443 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3444 file, linenum, args[0]);
3445 err_code |= ERR_WARN;
3446 }
3447
Willy Tarreauff011f22011-01-06 17:51:27 +01003448 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003449
Willy Tarreauff011f22011-01-06 17:51:27 +01003450 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003451 err_code |= ERR_ALERT | ERR_ABORT;
3452 goto out;
3453 }
3454
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003455 err_code |= warnif_cond_conflicts(rule->cond,
3456 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3457 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003458 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003459
Willy Tarreaubaaee002006-06-26 02:48:02 +02003460 } else if (!strcmp(args[1], "auth")) {
3461 if (*(args[2]) == 0) {
3462 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3466 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_ALERT | ERR_ABORT;
3468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469 }
3470 } else if (!strcmp(args[1], "scope")) {
3471 if (*(args[2]) == 0) {
3472 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_ABORT;
3478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 }
3480 } else if (!strcmp(args[1], "enable")) {
3481 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3482 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_ABORT;
3484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003485 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003486 } else if (!strcmp(args[1], "hide-version")) {
3487 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3488 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_ABORT;
3490 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003491 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003492 } else if (!strcmp(args[1], "show-legends")) {
3493 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3494 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3495 err_code |= ERR_ALERT | ERR_ABORT;
3496 goto out;
3497 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003498 } else if (!strcmp(args[1], "show-node")) {
3499
3500 if (*args[2]) {
3501 int i;
3502 char c;
3503
3504 for (i=0; args[2][i]; i++) {
3505 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003506 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3507 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003508 break;
3509 }
3510
3511 if (!i || args[2][i]) {
3512 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3513 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3514 file, linenum, args[0], args[1]);
3515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
3517 }
3518 }
3519
3520 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3521 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3522 err_code |= ERR_ALERT | ERR_ABORT;
3523 goto out;
3524 }
3525 } else if (!strcmp(args[1], "show-desc")) {
3526 char *desc = NULL;
3527
3528 if (*args[2]) {
3529 int i, len=0;
3530 char *d;
3531
Willy Tarreau348acfe2014-04-14 15:00:39 +02003532 for (i = 2; *args[i]; i++)
3533 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003534
3535 desc = d = (char *)calloc(1, len);
3536
Willy Tarreau348acfe2014-04-14 15:00:39 +02003537 d += snprintf(d, desc + len - d, "%s", args[2]);
3538 for (i = 3; *args[i]; i++)
3539 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003540 }
3541
3542 if (!*args[2] && !global.desc)
3543 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3544 file, linenum, args[1]);
3545 else {
3546 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3547 free(desc);
3548 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3549 err_code |= ERR_ALERT | ERR_ABORT;
3550 goto out;
3551 }
3552 free(desc);
3553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003555stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003556 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 +01003557 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 }
3561 }
3562 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003563 int optnum;
3564
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003565 if (*(args[1]) == '\0') {
3566 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3567 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003571
3572 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3573 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003574 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3575 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3576 file, linenum, cfg_opts[optnum].name);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
Willy Tarreau93893792009-07-23 13:19:11 +02003580 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3581 err_code |= ERR_WARN;
3582 goto out;
3583 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003584
Willy Tarreau3842f002009-06-14 11:39:52 +02003585 curproxy->no_options &= ~cfg_opts[optnum].val;
3586 curproxy->options &= ~cfg_opts[optnum].val;
3587
3588 switch (kwm) {
3589 case KWM_STD:
3590 curproxy->options |= cfg_opts[optnum].val;
3591 break;
3592 case KWM_NO:
3593 curproxy->no_options |= cfg_opts[optnum].val;
3594 break;
3595 case KWM_DEF: /* already cleared */
3596 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003597 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003598
Willy Tarreau93893792009-07-23 13:19:11 +02003599 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003600 }
3601 }
3602
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003603 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3604 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003605 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3606 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3607 file, linenum, cfg_opts2[optnum].name);
3608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
3610 }
Willy Tarreau93893792009-07-23 13:19:11 +02003611 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3612 err_code |= ERR_WARN;
3613 goto out;
3614 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003615
Willy Tarreau3842f002009-06-14 11:39:52 +02003616 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3617 curproxy->options2 &= ~cfg_opts2[optnum].val;
3618
3619 switch (kwm) {
3620 case KWM_STD:
3621 curproxy->options2 |= cfg_opts2[optnum].val;
3622 break;
3623 case KWM_NO:
3624 curproxy->no_options2 |= cfg_opts2[optnum].val;
3625 break;
3626 case KWM_DEF: /* already cleared */
3627 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003628 }
Willy Tarreau93893792009-07-23 13:19:11 +02003629 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003630 }
3631 }
3632
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003633 /* HTTP options override each other. They can be cancelled using
3634 * "no option xxx" which only switches to default mode if the mode
3635 * was this one (useful for cancelling options set in defaults
3636 * sections).
3637 */
3638 if (strcmp(args[1], "httpclose") == 0) {
3639 if (kwm == KWM_STD) {
3640 curproxy->options &= ~PR_O_HTTP_MODE;
3641 curproxy->options |= PR_O_HTTP_PCL;
3642 goto out;
3643 }
3644 else if (kwm == KWM_NO) {
3645 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3646 curproxy->options &= ~PR_O_HTTP_MODE;
3647 goto out;
3648 }
3649 }
3650 else if (strcmp(args[1], "forceclose") == 0) {
3651 if (kwm == KWM_STD) {
3652 curproxy->options &= ~PR_O_HTTP_MODE;
3653 curproxy->options |= PR_O_HTTP_FCL;
3654 goto out;
3655 }
3656 else if (kwm == KWM_NO) {
3657 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3658 curproxy->options &= ~PR_O_HTTP_MODE;
3659 goto out;
3660 }
3661 }
3662 else if (strcmp(args[1], "http-server-close") == 0) {
3663 if (kwm == KWM_STD) {
3664 curproxy->options &= ~PR_O_HTTP_MODE;
3665 curproxy->options |= PR_O_HTTP_SCL;
3666 goto out;
3667 }
3668 else if (kwm == KWM_NO) {
3669 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3670 curproxy->options &= ~PR_O_HTTP_MODE;
3671 goto out;
3672 }
3673 }
3674 else if (strcmp(args[1], "http-keep-alive") == 0) {
3675 if (kwm == KWM_STD) {
3676 curproxy->options &= ~PR_O_HTTP_MODE;
3677 curproxy->options |= PR_O_HTTP_KAL;
3678 goto out;
3679 }
3680 else if (kwm == KWM_NO) {
3681 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3682 curproxy->options &= ~PR_O_HTTP_MODE;
3683 goto out;
3684 }
3685 }
3686 else if (strcmp(args[1], "http-tunnel") == 0) {
3687 if (kwm == KWM_STD) {
3688 curproxy->options &= ~PR_O_HTTP_MODE;
3689 curproxy->options |= PR_O_HTTP_TUN;
3690 goto out;
3691 }
3692 else if (kwm == KWM_NO) {
3693 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3694 curproxy->options &= ~PR_O_HTTP_MODE;
3695 goto out;
3696 }
3697 }
3698
Willy Tarreau3842f002009-06-14 11:39:52 +02003699 if (kwm != KWM_STD) {
3700 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003701 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003704 }
3705
Emeric Brun3a058f32009-06-30 18:26:00 +02003706 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003707 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003709 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003710 if (*(args[2]) != '\0') {
3711 if (!strcmp(args[2], "clf")) {
3712 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003713 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003714 } else {
3715 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003718 }
3719 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003720 if (curproxy->conf.logformat_string != default_http_log_format &&
3721 curproxy->conf.logformat_string != default_tcp_log_format &&
3722 curproxy->conf.logformat_string != clf_http_log_format)
3723 free(curproxy->conf.logformat_string);
3724 curproxy->conf.logformat_string = logformat;
3725
3726 free(curproxy->conf.lfs_file);
3727 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3728 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003729 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003730 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003732 if (curproxy->conf.logformat_string != default_http_log_format &&
3733 curproxy->conf.logformat_string != default_tcp_log_format &&
3734 curproxy->conf.logformat_string != clf_http_log_format)
3735 free(curproxy->conf.logformat_string);
3736 curproxy->conf.logformat_string = default_tcp_log_format;
3737
3738 free(curproxy->conf.lfs_file);
3739 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3740 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 else if (!strcmp(args[1], "tcpka")) {
3743 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003744 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003746
3747 if (curproxy->cap & PR_CAP_FE)
3748 curproxy->options |= PR_O_TCP_CLI_KA;
3749 if (curproxy->cap & PR_CAP_BE)
3750 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
3752 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003753 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_WARN;
3755
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003757 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003758 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003759 curproxy->options2 &= ~PR_O2_CHK_ANY;
3760 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 if (!*args[2]) { /* no argument */
3762 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3763 curproxy->check_len = strlen(DEF_CHECK_REQ);
3764 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003765 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 curproxy->check_req = (char *)malloc(reqlen);
3767 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003768 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003770 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 if (*args[4])
3772 reqlen += strlen(args[4]);
3773 else
3774 reqlen += strlen("HTTP/1.0");
3775
3776 curproxy->check_req = (char *)malloc(reqlen);
3777 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003778 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003780 }
3781 else if (!strcmp(args[1], "ssl-hello-chk")) {
3782 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003785
Willy Tarreaua534fea2008-08-03 12:19:50 +02003786 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003787 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003788 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003789 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
Willy Tarreau23677902007-05-08 23:50:35 +02003791 else if (!strcmp(args[1], "smtpchk")) {
3792 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003793 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003794 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003795 curproxy->options2 &= ~PR_O2_CHK_ANY;
3796 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003797
3798 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3799 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3800 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3801 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3802 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3803 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3804 curproxy->check_req = (char *)malloc(reqlen);
3805 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3806 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3807 } else {
3808 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3809 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3810 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3811 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3812 }
3813 }
3814 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003815 else if (!strcmp(args[1], "pgsql-check")) {
3816 /* use PostgreSQL request to check servers' health */
3817 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3818 err_code |= ERR_WARN;
3819
3820 free(curproxy->check_req);
3821 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003822 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003823 curproxy->options2 |= PR_O2_PGSQL_CHK;
3824
3825 if (*(args[2])) {
3826 int cur_arg = 2;
3827
3828 while (*(args[cur_arg])) {
3829 if (strcmp(args[cur_arg], "user") == 0) {
3830 char * packet;
3831 uint32_t packet_len;
3832 uint32_t pv;
3833
3834 /* suboption header - needs additional argument for it */
3835 if (*(args[cur_arg+1]) == 0) {
3836 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3837 file, linenum, args[0], args[1], args[cur_arg]);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840 }
3841
3842 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3843 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3844 pv = htonl(0x30000); /* protocol version 3.0 */
3845
3846 packet = (char*) calloc(1, packet_len);
3847
3848 memcpy(packet + 4, &pv, 4);
3849
3850 /* copy "user" */
3851 memcpy(packet + 8, "user", 4);
3852
3853 /* copy username */
3854 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3855
3856 free(curproxy->check_req);
3857 curproxy->check_req = packet;
3858 curproxy->check_len = packet_len;
3859
3860 packet_len = htonl(packet_len);
3861 memcpy(packet, &packet_len, 4);
3862 cur_arg += 2;
3863 } else {
3864 /* unknown suboption - catchall */
3865 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3866 file, linenum, args[0], args[1]);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870 } /* end while loop */
3871 }
3872 }
3873
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003874 else if (!strcmp(args[1], "redis-check")) {
3875 /* use REDIS PING request to check servers' health */
3876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3877 err_code |= ERR_WARN;
3878
3879 free(curproxy->check_req);
3880 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003881 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003882 curproxy->options2 |= PR_O2_REDIS_CHK;
3883
3884 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3885 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3886 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3887 }
3888
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003889 else if (!strcmp(args[1], "mysql-check")) {
3890 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003891 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3892 err_code |= ERR_WARN;
3893
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003894 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003895 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003896 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003897 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003898
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003899 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003900 * const char mysql40_client_auth_pkt[] = {
3901 * "\x0e\x00\x00" // packet length
3902 * "\x01" // packet number
3903 * "\x00\x00" // client capabilities
3904 * "\x00\x00\x01" // max packet
3905 * "haproxy\x00" // username (null terminated string)
3906 * "\x00" // filler (always 0x00)
3907 * "\x01\x00\x00" // packet length
3908 * "\x00" // packet number
3909 * "\x01" // COM_QUIT command
3910 * };
3911 */
3912
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003913 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3914 * const char mysql41_client_auth_pkt[] = {
3915 * "\x0e\x00\x00\" // packet length
3916 * "\x01" // packet number
3917 * "\x00\x00\x00\x00" // client capabilities
3918 * "\x00\x00\x00\x01" // max packet
3919 * "\x21" // character set (UTF-8)
3920 * char[23] // All zeroes
3921 * "haproxy\x00" // username (null terminated string)
3922 * "\x00" // filler (always 0x00)
3923 * "\x01\x00\x00" // packet length
3924 * "\x00" // packet number
3925 * "\x01" // COM_QUIT command
3926 * };
3927 */
3928
3929
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003930 if (*(args[2])) {
3931 int cur_arg = 2;
3932
3933 while (*(args[cur_arg])) {
3934 if (strcmp(args[cur_arg], "user") == 0) {
3935 char *mysqluser;
3936 int packetlen, reqlen, userlen;
3937
3938 /* suboption header - needs additional argument for it */
3939 if (*(args[cur_arg+1]) == 0) {
3940 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3941 file, linenum, args[0], args[1], args[cur_arg]);
3942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
3944 }
3945 mysqluser = args[cur_arg + 1];
3946 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003947
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003948 if (*(args[cur_arg+2])) {
3949 if (!strcmp(args[cur_arg+2], "post-41")) {
3950 packetlen = userlen + 7 + 27;
3951 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003952
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003953 free(curproxy->check_req);
3954 curproxy->check_req = (char *)calloc(1, reqlen);
3955 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003956
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003957 snprintf(curproxy->check_req, 4, "%c%c%c",
3958 ((unsigned char) packetlen & 0xff),
3959 ((unsigned char) (packetlen >> 8) & 0xff),
3960 ((unsigned char) (packetlen >> 16) & 0xff));
3961
3962 curproxy->check_req[3] = 1;
3963 curproxy->check_req[5] = 130;
3964 curproxy->check_req[11] = 1;
3965 curproxy->check_req[12] = 33;
3966 memcpy(&curproxy->check_req[36], mysqluser, userlen);
3967 curproxy->check_req[36 + userlen + 1 + 1] = 1;
3968 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
3969 cur_arg += 3;
3970 } else {
3971 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975 } else {
3976 packetlen = userlen + 7;
3977 reqlen = packetlen + 9;
3978
3979 free(curproxy->check_req);
3980 curproxy->check_req = (char *)calloc(1, reqlen);
3981 curproxy->check_len = reqlen;
3982
3983 snprintf(curproxy->check_req, 4, "%c%c%c",
3984 ((unsigned char) packetlen & 0xff),
3985 ((unsigned char) (packetlen >> 8) & 0xff),
3986 ((unsigned char) (packetlen >> 16) & 0xff));
3987
3988 curproxy->check_req[3] = 1;
3989 curproxy->check_req[5] = 128;
3990 curproxy->check_req[8] = 1;
3991 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3992 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3993 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3994 cur_arg += 2;
3995 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003996 } else {
3997 /* unknown suboption - catchall */
3998 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3999 file, linenum, args[0], args[1]);
4000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
4002 }
4003 } /* end while loop */
4004 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004005 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004006 else if (!strcmp(args[1], "ldap-check")) {
4007 /* use LDAP request to check servers' health */
4008 free(curproxy->check_req);
4009 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004010 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004011 curproxy->options2 |= PR_O2_LDAP_CHK;
4012
4013 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4014 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4015 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4016 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004017 else if (!strcmp(args[1], "tcp-check")) {
4018 /* use raw TCPCHK send/expect to check servers' health */
4019 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4020 err_code |= ERR_WARN;
4021
4022 free(curproxy->check_req);
4023 curproxy->check_req = NULL;
4024 curproxy->options2 &= ~PR_O2_CHK_ANY;
4025 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4026 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004027 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004028 int cur_arg;
4029
4030 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4031 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004032 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004033
Willy Tarreau87cf5142011-08-19 22:57:24 +02004034 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004035
4036 free(curproxy->fwdfor_hdr_name);
4037 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4038 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4039
4040 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4041 cur_arg = 2;
4042 while (*(args[cur_arg])) {
4043 if (!strcmp(args[cur_arg], "except")) {
4044 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004045 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004046 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4047 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004050 }
4051 /* flush useless bits */
4052 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004053 cur_arg += 2;
4054 } else if (!strcmp(args[cur_arg], "header")) {
4055 /* suboption header - needs additional argument for it */
4056 if (*(args[cur_arg+1]) == 0) {
4057 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4058 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004061 }
4062 free(curproxy->fwdfor_hdr_name);
4063 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4064 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4065 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004066 } else if (!strcmp(args[cur_arg], "if-none")) {
4067 curproxy->options &= ~PR_O_FF_ALWAYS;
4068 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004069 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004070 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004071 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004072 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004075 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004076 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004077 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004078 else if (!strcmp(args[1], "originalto")) {
4079 int cur_arg;
4080
4081 /* insert x-original-to field, but not for the IP address listed as an except.
4082 * set default options (ie: bitfield, header name, etc)
4083 */
4084
4085 curproxy->options |= PR_O_ORGTO;
4086
4087 free(curproxy->orgto_hdr_name);
4088 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4089 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4090
Willy Tarreau87cf5142011-08-19 22:57:24 +02004091 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004092 cur_arg = 2;
4093 while (*(args[cur_arg])) {
4094 if (!strcmp(args[cur_arg], "except")) {
4095 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004096 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 +02004097 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4098 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004101 }
4102 /* flush useless bits */
4103 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4104 cur_arg += 2;
4105 } else if (!strcmp(args[cur_arg], "header")) {
4106 /* suboption header - needs additional argument for it */
4107 if (*(args[cur_arg+1]) == 0) {
4108 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4109 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004112 }
4113 free(curproxy->orgto_hdr_name);
4114 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4115 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4116 cur_arg += 2;
4117 } else {
4118 /* unknown suboption - catchall */
4119 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4120 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004123 }
4124 } /* end while loop */
4125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 else {
4127 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 }
Willy Tarreau93893792009-07-23 13:19:11 +02004131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004133 else if (!strcmp(args[0], "default_backend")) {
4134 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004136
4137 if (*(args[1]) == 0) {
4138 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004141 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004142 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004143 curproxy->defbe.name = strdup(args[1]);
4144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004146 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004147 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004148
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004149 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4150 Warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'option redispatch', and will not be supported by future versions.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004151 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 /* enable reconnections to dispatch */
4154 curproxy->options |= PR_O_REDISP;
4155 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004156 else if (!strcmp(args[0], "http-check")) {
4157 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004158 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004159
4160 if (strcmp(args[1], "disable-on-404") == 0) {
4161 /* enable a graceful server shutdown on an HTTP 404 response */
4162 curproxy->options |= PR_O_DISABLE404;
4163 }
Willy Tarreauef781042010-01-27 11:53:01 +01004164 else if (strcmp(args[1], "send-state") == 0) {
4165 /* enable emission of the apparent state of a server in HTTP checks */
4166 curproxy->options2 |= PR_O2_CHK_SNDST;
4167 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004168 else if (strcmp(args[1], "expect") == 0) {
4169 const char *ptr_arg;
4170 int cur_arg;
4171
4172 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4173 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
4177
4178 cur_arg = 2;
4179 /* consider exclamation marks, sole or at the beginning of a word */
4180 while (*(ptr_arg = args[cur_arg])) {
4181 while (*ptr_arg == '!') {
4182 curproxy->options2 ^= PR_O2_EXP_INV;
4183 ptr_arg++;
4184 }
4185 if (*ptr_arg)
4186 break;
4187 cur_arg++;
4188 }
4189 /* now ptr_arg points to the beginning of a word past any possible
4190 * exclamation mark, and cur_arg is the argument which holds this word.
4191 */
4192 if (strcmp(ptr_arg, "status") == 0) {
4193 if (!*(args[cur_arg + 1])) {
4194 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4195 file, linenum, args[0], args[1], ptr_arg);
4196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
4198 }
4199 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004200 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004201 curproxy->expect_str = strdup(args[cur_arg + 1]);
4202 }
4203 else if (strcmp(ptr_arg, "string") == 0) {
4204 if (!*(args[cur_arg + 1])) {
4205 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4206 file, linenum, args[0], args[1], ptr_arg);
4207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
4209 }
4210 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004211 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004212 curproxy->expect_str = strdup(args[cur_arg + 1]);
4213 }
4214 else if (strcmp(ptr_arg, "rstatus") == 0) {
4215 if (!*(args[cur_arg + 1])) {
4216 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4217 file, linenum, args[0], args[1], ptr_arg);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220 }
4221 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004222 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004223 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004224 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004225 free(curproxy->expect_regex);
4226 curproxy->expect_regex = NULL;
4227 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004228 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004229 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4230 error = NULL;
4231 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4232 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4233 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4234 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 }
4238 }
4239 else if (strcmp(ptr_arg, "rstring") == 0) {
4240 if (!*(args[cur_arg + 1])) {
4241 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4242 file, linenum, args[0], args[1], ptr_arg);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
4245 }
4246 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004247 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004248 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004249 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004250 free(curproxy->expect_regex);
4251 curproxy->expect_regex = NULL;
4252 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004253 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004254 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4255 error = NULL;
4256 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4257 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4258 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4259 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263 }
4264 else {
4265 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4266 file, linenum, args[0], args[1], ptr_arg);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004271 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004272 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 +02004273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004275 }
4276 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004277 else if (!strcmp(args[0], "tcp-check")) {
4278 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4279 err_code |= ERR_WARN;
4280
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004281 if (strcmp(args[1], "connect") == 0) {
4282 const char *ptr_arg;
4283 int cur_arg;
4284 struct tcpcheck_rule *tcpcheck;
4285 struct list *l;
4286
4287 /* check if first rule is also a 'connect' action */
4288 l = (struct list *)&curproxy->tcpcheck_rules;
4289 if (l->p != l->n) {
4290 tcpcheck = (struct tcpcheck_rule *)l->n;
4291 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4292 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4293 file, linenum);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297 }
4298
4299 cur_arg = 2;
4300 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4301 tcpcheck->action = TCPCHK_ACT_CONNECT;
4302
4303 /* parsing each parameters to fill up the rule */
4304 while (*(ptr_arg = args[cur_arg])) {
4305 /* tcp port */
4306 if (strcmp(args[cur_arg], "port") == 0) {
4307 if ( (atol(args[cur_arg + 1]) > 65535) ||
4308 (atol(args[cur_arg + 1]) < 1) ){
4309 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4310 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
4313 }
4314 tcpcheck->port = atol(args[cur_arg + 1]);
4315 cur_arg += 2;
4316 }
4317 /* send proxy protocol */
4318 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4319 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4320 cur_arg++;
4321 }
4322#ifdef USE_OPENSSL
4323 else if (strcmp(args[cur_arg], "ssl") == 0) {
4324 curproxy->options |= PR_O_TCPCHK_SSL;
4325 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4326 cur_arg++;
4327 }
4328#endif /* USE_OPENSSL */
4329 else {
4330#ifdef USE_OPENSSL
4331 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4332#else /* USE_OPENSSL */
4333 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4334#endif /* USE_OPENSSL */
4335 file, linenum, args[0], args[1], args[cur_arg]);
4336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
4338 }
4339
4340 }
4341
4342 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4343 }
4344 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004345 if (! *(args[2]) ) {
4346 /* SEND string expected */
4347 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4348 file, linenum, args[0], args[1], args[2]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 } else {
4352 struct tcpcheck_rule *tcpcheck;
4353
4354 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4355
4356 tcpcheck->action = TCPCHK_ACT_SEND;
4357 tcpcheck->string_len = strlen(args[2]);
4358 tcpcheck->string = strdup(args[2]);
4359 tcpcheck->expect_regex = NULL;
4360
4361 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4362 }
4363 }
4364 else if (strcmp(args[1], "send-binary") == 0) {
4365 if (! *(args[2]) ) {
4366 /* SEND binary string expected */
4367 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4368 file, linenum, args[0], args[1], args[2]);
4369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 } else {
4372 struct tcpcheck_rule *tcpcheck;
4373 char *err = NULL;
4374
4375 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4376
4377 tcpcheck->action = TCPCHK_ACT_SEND;
4378 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4379 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4380 file, linenum, args[0], args[1], args[2], err);
4381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
4383 }
4384 tcpcheck->expect_regex = NULL;
4385
4386 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4387 }
4388 }
4389 else if (strcmp(args[1], "expect") == 0) {
4390 const char *ptr_arg;
4391 int cur_arg;
4392 int inverse = 0;
4393
4394 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4395 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399
4400 cur_arg = 2;
4401 /* consider exclamation marks, sole or at the beginning of a word */
4402 while (*(ptr_arg = args[cur_arg])) {
4403 while (*ptr_arg == '!') {
4404 inverse = !inverse;
4405 ptr_arg++;
4406 }
4407 if (*ptr_arg)
4408 break;
4409 cur_arg++;
4410 }
4411 /* now ptr_arg points to the beginning of a word past any possible
4412 * exclamation mark, and cur_arg is the argument which holds this word.
4413 */
4414 if (strcmp(ptr_arg, "binary") == 0) {
4415 if (!*(args[cur_arg + 1])) {
4416 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4417 file, linenum, args[0], args[1], ptr_arg);
4418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
4420 }
4421 struct tcpcheck_rule *tcpcheck;
4422 char *err = NULL;
4423
4424 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4425
4426 tcpcheck->action = TCPCHK_ACT_EXPECT;
4427 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4428 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4429 file, linenum, args[0], args[1], args[2], err);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
4433 tcpcheck->expect_regex = NULL;
4434 tcpcheck->inverse = inverse;
4435
4436 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4437 }
4438 else if (strcmp(ptr_arg, "string") == 0) {
4439 if (!*(args[cur_arg + 1])) {
4440 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4441 file, linenum, args[0], args[1], ptr_arg);
4442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
4444 }
4445 struct tcpcheck_rule *tcpcheck;
4446
4447 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4448
4449 tcpcheck->action = TCPCHK_ACT_EXPECT;
4450 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4451 tcpcheck->string = strdup(args[cur_arg + 1]);
4452 tcpcheck->expect_regex = NULL;
4453 tcpcheck->inverse = inverse;
4454
4455 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4456 }
4457 else if (strcmp(ptr_arg, "rstring") == 0) {
4458 if (!*(args[cur_arg + 1])) {
4459 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4460 file, linenum, args[0], args[1], ptr_arg);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
4464 struct tcpcheck_rule *tcpcheck;
4465
4466 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4467
4468 tcpcheck->action = TCPCHK_ACT_EXPECT;
4469 tcpcheck->string_len = 0;
4470 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004471 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4472 error = NULL;
4473 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4474 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4475 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4476 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
4479 }
4480 tcpcheck->inverse = inverse;
4481
4482 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4483 }
4484 else {
4485 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4486 file, linenum, args[0], args[1], ptr_arg);
4487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
4489 }
4490 }
4491 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004492 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
4496 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004497 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004498 if (curproxy == &defproxy) {
4499 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004502 }
4503
Willy Tarreaub80c2302007-11-30 20:51:32 +01004504 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004506
4507 if (strcmp(args[1], "fail") == 0) {
4508 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004509 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004510 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4511 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004514 }
4515
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004516 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4517 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4518 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004521 }
4522 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4523 }
4524 else {
4525 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004528 }
4529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530#ifdef TPROXY
4531 else if (!strcmp(args[0], "transparent")) {
4532 /* enable transparent proxy connections */
4533 curproxy->options |= PR_O_TRANSP;
4534 }
4535#endif
4536 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004537 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004539
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 if (*(args[1]) == 0) {
4541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 }
4545 curproxy->maxconn = atol(args[1]);
4546 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004547 else if (!strcmp(args[0], "backlog")) { /* backlog */
4548 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004549 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004550
4551 if (*(args[1]) == 0) {
4552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004555 }
4556 curproxy->backlog = atol(args[1]);
4557 }
Willy Tarreau86034312006-12-29 00:10:33 +01004558 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004559 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004560 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004561
Willy Tarreau86034312006-12-29 00:10:33 +01004562 if (*(args[1]) == 0) {
4563 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004566 }
4567 curproxy->fullconn = atol(args[1]);
4568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4570 if (*(args[1]) == 0) {
4571 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004575 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4576 if (err) {
4577 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4578 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004581 }
4582 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
4584 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004585 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004586 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004587 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004588
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 if (curproxy == &defproxy) {
4590 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004593 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004594 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004596
Willy Tarreau902636f2013-03-10 19:44:48 +01004597 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004598 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004599 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004600 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004601 goto out;
4602 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004603
4604 proto = protocol_by_family(sk->ss_family);
4605 if (!proto || !proto->connect) {
4606 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4607 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
4611
4612 if (port1 != port2) {
4613 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4614 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004618
4619 if (!port1) {
4620 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4621 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004625
Willy Tarreaud5191e72010-02-09 20:50:45 +01004626 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004627 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 }
4629 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004630 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004631 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004632
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004633 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4634 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004638 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004639 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004640 /**
4641 * The syntax for hash-type config element is
4642 * hash-type {map-based|consistent} [[<algo>] avalanche]
4643 *
4644 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4645 */
4646 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004647
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4649 err_code |= ERR_WARN;
4650
4651 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004652 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4653 }
4654 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004655 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4656 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004657 else if (strcmp(args[1], "avalanche") == 0) {
4658 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]);
4659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004661 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004662 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004663 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
Bhaskar98634f02013-10-29 23:30:51 -04004667
4668 /* set the hash function to use */
4669 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004670 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004671 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004672
4673 /* if consistent with no argument, then avalanche modifier is also applied */
4674 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4675 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004676 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004677 /* set the hash function */
4678 if (!strcmp(args[2], "sdbm")) {
4679 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4680 }
4681 else if (!strcmp(args[2], "djb2")) {
4682 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004683 } else if (!strcmp(args[2], "wt6")) {
4684 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004685 }
4686 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004687 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 -05004688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
4691
4692 /* set the hash modifier */
4693 if (!strcmp(args[3], "avalanche")) {
4694 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4695 }
4696 else if (*args[3]) {
4697 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004701 }
William Lallemanda73203e2012-03-12 12:48:57 +01004702 }
William Lallemanda73203e2012-03-12 12:48:57 +01004703 else if (strcmp(args[0], "unique-id-format") == 0) {
4704 if (!*(args[1])) {
4705 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708 }
William Lallemand3203ff42012-11-11 17:30:56 +01004709 if (*(args[2])) {
4710 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
4713 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004714 free(curproxy->conf.uniqueid_format_string);
4715 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004716
Willy Tarreau62a61232013-04-12 18:13:46 +02004717 free(curproxy->conf.uif_file);
4718 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4719 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004720 }
William Lallemanda73203e2012-03-12 12:48:57 +01004721
4722 else if (strcmp(args[0], "unique-id-header") == 0) {
4723 if (!*(args[1])) {
4724 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
4727 }
4728 free(curproxy->header_unique_id);
4729 curproxy->header_unique_id = strdup(args[1]);
4730 }
4731
William Lallemand723b73a2012-02-08 16:37:49 +01004732 else if (strcmp(args[0], "log-format") == 0) {
4733 if (!*(args[1])) {
4734 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737 }
William Lallemand3203ff42012-11-11 17:30:56 +01004738 if (*(args[2])) {
4739 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004743
Willy Tarreau62a61232013-04-12 18:13:46 +02004744 if (curproxy->conf.logformat_string != default_http_log_format &&
4745 curproxy->conf.logformat_string != default_tcp_log_format &&
4746 curproxy->conf.logformat_string != clf_http_log_format)
4747 free(curproxy->conf.logformat_string);
4748 curproxy->conf.logformat_string = strdup(args[1]);
4749
4750 free(curproxy->conf.lfs_file);
4751 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4752 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004753
4754 /* get a chance to improve log-format error reporting by
4755 * reporting the correct line-number when possible.
4756 */
4757 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4758 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4759 file, linenum, curproxy->id);
4760 err_code |= ERR_WARN;
4761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
William Lallemand723b73a2012-02-08 16:37:49 +01004763
William Lallemand0f99e342011-10-12 17:50:54 +02004764 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4765 /* delete previous herited or defined syslog servers */
4766 struct logsrv *back;
4767
4768 if (*(args[1]) != 0) {
4769 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
4773
William Lallemand723b73a2012-02-08 16:37:49 +01004774 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4775 LIST_DEL(&tmplogsrv->list);
4776 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004777 }
4778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004780 struct logsrv *logsrv;
4781
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004783 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004784 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004785 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004786 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004787 LIST_INIT(&node->list);
4788 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 }
4791 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004792 struct sockaddr_storage *sk;
4793 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004794
4795 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796
William Lallemand0f99e342011-10-12 17:50:54 +02004797 logsrv->facility = get_log_facility(args[2]);
4798 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 }
4804
William Lallemand0f99e342011-10-12 17:50:54 +02004805 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004807 logsrv->level = get_log_level(args[3]);
4808 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
4812
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 }
4814 }
4815
William Lallemand0f99e342011-10-12 17:50:54 +02004816 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004817 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004818 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004819 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004820 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004824 }
4825 }
4826
Willy Tarreau902636f2013-03-10 19:44:48 +01004827 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004828 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004829 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004830 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004831 goto out;
4832 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004833
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004834 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004835
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004836 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004837 if (port1 != port2) {
4838 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4839 file, linenum, args[0], args[1]);
4840 err_code |= ERR_ALERT | ERR_FATAL;
4841 goto out;
4842 }
4843
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004844 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004845 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
William Lallemand0f99e342011-10-12 17:50:54 +02004847
4848 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
4850 else {
4851 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4852 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
4856 }
4857 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004858 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004859 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004860 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004861 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004862
Willy Tarreau977b8e42006-12-29 14:19:17 +01004863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004864 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004865
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004867 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4868 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004872
4873 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004874 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4875 free(curproxy->conn_src.iface_name);
4876 curproxy->conn_src.iface_name = NULL;
4877 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004878
Willy Tarreau902636f2013-03-10 19:44:48 +01004879 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004880 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004881 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004882 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004884 goto out;
4885 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004886
4887 proto = protocol_by_family(sk->ss_family);
4888 if (!proto || !proto->connect) {
4889 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004890 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004894
4895 if (port1 != port2) {
4896 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4897 file, linenum, args[0], args[1]);
4898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
4900 }
4901
Willy Tarreauef9a3602012-12-08 22:29:20 +01004902 curproxy->conn_src.source_addr = *sk;
4903 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004904
4905 cur_arg = 2;
4906 while (*(args[cur_arg])) {
4907 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004908#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4909#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02004910 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004911 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4912 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004915 }
4916#endif
4917 if (!*args[cur_arg + 1]) {
4918 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4919 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004922 }
4923
4924 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004925 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4926 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004927 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004928 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4929 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004930 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4931 char *name, *end;
4932
4933 name = args[cur_arg+1] + 7;
4934 while (isspace(*name))
4935 name++;
4936
4937 end = name;
4938 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4939 end++;
4940
Willy Tarreauef9a3602012-12-08 22:29:20 +01004941 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4942 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4943 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4944 curproxy->conn_src.bind_hdr_len = end - name;
4945 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4946 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4947 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004948
4949 /* now look for an occurrence number */
4950 while (isspace(*end))
4951 end++;
4952 if (*end == ',') {
4953 end++;
4954 name = end;
4955 if (*end == '-')
4956 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004957 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004958 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004959 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004960 }
4961
Willy Tarreauef9a3602012-12-08 22:29:20 +01004962 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004963 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4964 " occurrences values smaller than %d.\n",
4965 file, linenum, MAX_HDR_HISTORY);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004969 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004970 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004971
Willy Tarreau902636f2013-03-10 19:44:48 +01004972 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004973 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004974 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004975 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004976 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004977 goto out;
4978 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004979
4980 proto = protocol_by_family(sk->ss_family);
4981 if (!proto || !proto->connect) {
4982 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4983 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004987
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004988 if (port1 != port2) {
4989 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4990 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004994 curproxy->conn_src.tproxy_addr = *sk;
4995 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004996 }
4997 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004998#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004999 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005000#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005001#else /* no TPROXY support */
5002 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005003 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005006#endif
5007 cur_arg += 2;
5008 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005009 }
5010
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005011 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5012#ifdef SO_BINDTODEVICE
5013 if (!*args[cur_arg + 1]) {
5014 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005018 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005019 free(curproxy->conn_src.iface_name);
5020 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5021 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005022 global.last_checks |= LSTCHK_NETADM;
5023#else
5024 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5025 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005028#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005029 cur_arg += 2;
5030 continue;
5031 }
5032 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005033 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005038 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5039 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5040 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005045 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005051
5052 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005053 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005054 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005055 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
5058 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005059 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005060 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005061 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005067 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005068 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
5072 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005074 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005075 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 }
5079 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005081 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005082 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005083 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005086 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005087 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005088 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005089 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005090 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005091 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005092 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005093 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005095 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005096 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005098 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005099
5100 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5101 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005102 }
5103 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005104 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005105 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005106 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005108 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005109
5110 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5111 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005114 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5116 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120
5121 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005122 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005123 args[0], args[1], args[2], (const char **)args+3);
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], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005129 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005130 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
5134 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005135 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005136 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005137 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
5141 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005143 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005144 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005150 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005151 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005155 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005157 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005158 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005160 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005163 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005164
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 if (curproxy == &defproxy) {
5166 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005170 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005171 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 if (*(args[1]) == 0) {
5174 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005178
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005179 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005180 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5181 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5182 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005186 err_code |= warnif_cond_conflicts(cond,
5187 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5188 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005189 }
5190 else if (*args[2]) {
5191 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5192 file, linenum, args[0], args[2]);
5193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
5195 }
5196
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005197 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005198 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005199 wl->s = strdup(args[1]);
5200 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005201 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
5203 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005210
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005212 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005213 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 }
5217 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005219 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005220 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
5224 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005226 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005227 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
5231 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
5238
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005241 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
5245 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005247 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
5252 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
5259 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005260 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005261
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 if (curproxy == &defproxy) {
5263 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005267 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005268 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 if (*(args[1]) == 0) {
5271 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
5275
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005276 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005277 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5278 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5279 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005283 err_code |= warnif_cond_conflicts(cond,
5284 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5285 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005286 }
5287 else if (*args[2]) {
5288 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5289 file, linenum, args[0], args[2]);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
5292 }
5293
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005294 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005295 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005296 wl->s = strdup(args[1]);
5297 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
5299 else if (!strcmp(args[0], "errorloc") ||
5300 !strcmp(args[0], "errorloc302") ||
5301 !strcmp(args[0], "errorloc303")) { /* error location */
5302 int errnum, errlen;
5303 char *err;
5304
Willy Tarreau977b8e42006-12-29 14:19:17 +01005305 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005307
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005309 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313
5314 errnum = atol(args[1]);
5315 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005316 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5317 err = malloc(errlen);
5318 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005320 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5321 err = malloc(errlen);
5322 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 }
5324
Willy Tarreau0f772532006-12-23 20:51:41 +01005325 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5326 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005327 chunk_destroy(&curproxy->errmsg[rc]);
5328 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005329 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005332
5333 if (rc >= HTTP_ERR_SIZE) {
5334 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5335 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 free(err);
5337 }
5338 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005339 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5340 int errnum, errlen, fd;
5341 char *err;
5342 struct stat stat;
5343
5344 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005346
5347 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005348 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005351 }
5352
5353 fd = open(args[2], O_RDONLY);
5354 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5355 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5356 file, linenum, args[2], args[1]);
5357 if (fd >= 0)
5358 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005361 }
5362
Willy Tarreau27a674e2009-08-17 07:23:33 +02005363 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005364 errlen = stat.st_size;
5365 } else {
5366 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005367 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005368 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005369 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005370 }
5371
5372 err = malloc(errlen); /* malloc() must succeed during parsing */
5373 errnum = read(fd, err, errlen);
5374 if (errnum != errlen) {
5375 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5376 file, linenum, args[2], args[1]);
5377 close(fd);
5378 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005381 }
5382 close(fd);
5383
5384 errnum = atol(args[1]);
5385 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5386 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005387 chunk_destroy(&curproxy->errmsg[rc]);
5388 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005389 break;
5390 }
5391 }
5392
5393 if (rc >= HTTP_ERR_SIZE) {
5394 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5395 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005397 free(err);
5398 }
5399 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005400 else if (!strcmp(args[0], "compression")) {
5401 struct comp *comp;
5402 if (curproxy->comp == NULL) {
5403 comp = calloc(1, sizeof(struct comp));
5404 curproxy->comp = comp;
5405 } else {
5406 comp = curproxy->comp;
5407 }
5408
5409 if (!strcmp(args[1], "algo")) {
5410 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005411 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005412
William Lallemand82fe75c2012-10-23 10:25:10 +02005413 cur_arg = 2;
5414 if (!*args[cur_arg]) {
5415 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5416 file, linenum, args[0]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420 while (*(args[cur_arg])) {
5421 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5422 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5423 file, linenum, args[0], args[cur_arg]);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
William Lallemand552df672012-11-07 13:21:47 +01005427 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5428 curproxy->comp->algos->end(&ctx);
5429 } else {
5430 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5431 file, linenum, args[0], args[cur_arg]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005435 cur_arg ++;
5436 continue;
5437 }
5438 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005439 else if (!strcmp(args[1], "offload")) {
5440 comp->offload = 1;
5441 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005442 else if (!strcmp(args[1], "type")) {
5443 int cur_arg;
5444 cur_arg = 2;
5445 if (!*args[cur_arg]) {
5446 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5447 file, linenum, args[0]);
5448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
5451 while (*(args[cur_arg])) {
5452 comp_append_type(comp, args[cur_arg]);
5453 cur_arg ++;
5454 continue;
5455 }
5456 }
5457 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005458 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005459 file, linenum, args[0]);
5460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
5462 }
5463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005465 struct cfg_kw_list *kwl;
5466 int index;
5467
5468 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5469 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5470 if (kwl->kw[index].section != CFG_LISTEN)
5471 continue;
5472 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5473 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005474 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005475 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005476 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005479 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005480 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005481 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_WARN;
5483 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005484 }
Willy Tarreau93893792009-07-23 13:19:11 +02005485 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005486 }
5487 }
5488 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005489
Willy Tarreau6daf3432008-01-22 16:44:08 +01005490 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 }
Willy Tarreau93893792009-07-23 13:19:11 +02005494 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005495 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005496 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497}
5498
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005499int
5500cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5501{
5502
5503 int err_code = 0;
5504 const char *err;
5505
5506 if (!strcmp(args[0], "userlist")) { /* new userlist */
5507 struct userlist *newul;
5508
5509 if (!*args[1]) {
5510 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5511 file, linenum, args[0]);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515
5516 err = invalid_char(args[1]);
5517 if (err) {
5518 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5519 file, linenum, *err, args[0], args[1]);
5520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522 }
5523
5524 for (newul = userlist; newul; newul = newul->next)
5525 if (!strcmp(newul->name, args[1])) {
5526 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5527 file, linenum, args[1]);
5528 err_code |= ERR_WARN;
5529 goto out;
5530 }
5531
5532 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5533 if (!newul) {
5534 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5535 err_code |= ERR_ALERT | ERR_ABORT;
5536 goto out;
5537 }
5538
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005539 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005540 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005541 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5542 err_code |= ERR_ALERT | ERR_ABORT;
5543 goto out;
5544 }
5545
5546 newul->next = userlist;
5547 userlist = newul;
5548
5549 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005550 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005551 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005552 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005553
5554 if (!*args[1]) {
5555 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5556 file, linenum, args[0]);
5557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
5559 }
5560
5561 err = invalid_char(args[1]);
5562 if (err) {
5563 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5564 file, linenum, *err, args[0], args[1]);
5565 err_code |= ERR_ALERT | ERR_FATAL;
5566 goto out;
5567 }
5568
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005569 for (ag = userlist->groups; ag; ag = ag->next)
5570 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005571 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5572 file, linenum, args[1], userlist->name);
5573 err_code |= ERR_ALERT;
5574 goto out;
5575 }
5576
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005577 ag = calloc(1, sizeof(*ag));
5578 if (!ag) {
5579 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5580 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005581 goto out;
5582 }
5583
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005584 ag->name = strdup(args[1]);
5585 if (!ag) {
5586 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5587 err_code |= ERR_ALERT | ERR_ABORT;
5588 goto out;
5589 }
5590
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005591 cur_arg = 2;
5592
5593 while (*args[cur_arg]) {
5594 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005595 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005596 cur_arg += 2;
5597 continue;
5598 } else {
5599 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5600 file, linenum, args[0]);
5601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
5603 }
5604 }
5605
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005606 ag->next = userlist->groups;
5607 userlist->groups = ag;
5608
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005609 } else if (!strcmp(args[0], "user")) { /* new user */
5610 struct auth_users *newuser;
5611 int cur_arg;
5612
5613 if (!*args[1]) {
5614 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5615 file, linenum, args[0]);
5616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
5618 }
5619
5620 for (newuser = userlist->users; newuser; newuser = newuser->next)
5621 if (!strcmp(newuser->user, args[1])) {
5622 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5623 file, linenum, args[1], userlist->name);
5624 err_code |= ERR_ALERT;
5625 goto out;
5626 }
5627
5628 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5629 if (!newuser) {
5630 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5631 err_code |= ERR_ALERT | ERR_ABORT;
5632 goto out;
5633 }
5634
5635 newuser->user = strdup(args[1]);
5636
5637 newuser->next = userlist->users;
5638 userlist->users = newuser;
5639
5640 cur_arg = 2;
5641
5642 while (*args[cur_arg]) {
5643 if (!strcmp(args[cur_arg], "password")) {
5644#ifndef CONFIG_HAP_CRYPT
5645 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5646 file, linenum);
5647 err_code |= ERR_ALERT;
5648#endif
5649 newuser->pass = strdup(args[cur_arg + 1]);
5650 cur_arg += 2;
5651 continue;
5652 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5653 newuser->pass = strdup(args[cur_arg + 1]);
5654 newuser->flags |= AU_O_INSECURE;
5655 cur_arg += 2;
5656 continue;
5657 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005658 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005659 cur_arg += 2;
5660 continue;
5661 } else {
5662 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5663 file, linenum, args[0]);
5664 err_code |= ERR_ALERT | ERR_FATAL;
5665 goto out;
5666 }
5667 }
5668 } else {
5669 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5670 err_code |= ERR_ALERT | ERR_FATAL;
5671 }
5672
5673out:
5674 return err_code;
5675}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676
5677/*
5678 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005679 * Returns the error code, 0 if OK, or any combination of :
5680 * - ERR_ABORT: must abort ASAP
5681 * - ERR_FATAL: we can continue parsing but not start the service
5682 * - ERR_WARN: a warning has been emitted
5683 * - ERR_ALERT: an alert has been emitted
5684 * Only the two first ones can stop processing, the two others are just
5685 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005687int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005689 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690 FILE *f;
5691 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005692 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005693 struct cfg_section *cs = NULL;
5694 struct cfg_section *ics;
5695
5696 /* Register internal sections */
5697 if (!cfg_register_section("listen", cfg_parse_listen) ||
5698 !cfg_register_section("frontend", cfg_parse_listen) ||
5699 !cfg_register_section("backend", cfg_parse_listen) ||
5700 !cfg_register_section("ruleset", cfg_parse_listen) ||
5701 !cfg_register_section("defaults", cfg_parse_listen) ||
5702 !cfg_register_section("global", cfg_parse_global) ||
5703 !cfg_register_section("userlist", cfg_parse_users) ||
5704 !cfg_register_section("peers", cfg_parse_peers))
5705 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706
Willy Tarreaubaaee002006-06-26 02:48:02 +02005707 if ((f=fopen(file,"r")) == NULL)
5708 return -1;
5709
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005710 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005711 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005712 char *end;
5713 char *args[MAX_LINE_ARGS + 1];
5714 char *line = thisline;
5715
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 linenum++;
5717
5718 end = line + strlen(line);
5719
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005720 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5721 /* Check if we reached the limit and the last char is not \n.
5722 * Watch out for the last line without the terminating '\n'!
5723 */
5724 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005725 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005726 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005727 }
5728
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005730 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 line++;
5732
5733 arg = 0;
5734 args[arg] = line;
5735
5736 while (*line && arg < MAX_LINE_ARGS) {
5737 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5738 * C equivalent value. Other combinations left unchanged (eg: \1).
5739 */
5740 if (*line == '\\') {
5741 int skip = 0;
5742 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5743 *line = line[1];
5744 skip = 1;
5745 }
5746 else if (line[1] == 'r') {
5747 *line = '\r';
5748 skip = 1;
5749 }
5750 else if (line[1] == 'n') {
5751 *line = '\n';
5752 skip = 1;
5753 }
5754 else if (line[1] == 't') {
5755 *line = '\t';
5756 skip = 1;
5757 }
5758 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005759 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 unsigned char hex1, hex2;
5761 hex1 = toupper(line[2]) - '0';
5762 hex2 = toupper(line[3]) - '0';
5763 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5764 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5765 *line = (hex1<<4) + hex2;
5766 skip = 3;
5767 }
5768 else {
5769 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005770 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
5772 }
5773 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005774 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 end -= skip;
5776 }
5777 line++;
5778 }
5779 else if (*line == '#' || *line == '\n' || *line == '\r') {
5780 /* end of string, end of loop */
5781 *line = 0;
5782 break;
5783 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005784 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005786 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005787 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 line++;
5789 args[++arg] = line;
5790 }
5791 else {
5792 line++;
5793 }
5794 }
5795
5796 /* empty line */
5797 if (!**args)
5798 continue;
5799
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005800 if (*line) {
5801 /* we had to stop due to too many args.
5802 * Let's terminate the string, print the offending part then cut the
5803 * last arg.
5804 */
5805 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5806 line++;
5807 *line = '\0';
5808
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005809 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005810 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005811 err_code |= ERR_ALERT | ERR_FATAL;
5812 args[arg] = line;
5813 }
5814
Willy Tarreau540abe42007-05-02 20:50:16 +02005815 /* zero out remaining args and ensure that at least one entry
5816 * is zeroed out.
5817 */
5818 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 args[arg] = line;
5820 }
5821
Willy Tarreau3842f002009-06-14 11:39:52 +02005822 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005823 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005824 char *tmp;
5825
Willy Tarreau3842f002009-06-14 11:39:52 +02005826 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005827 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005828 for (arg=0; *args[arg+1]; arg++)
5829 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005830 *tmp = '\0'; // fix the next arg to \0
5831 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005832 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005833 else if (!strcmp(args[0], "default")) {
5834 kwm = KWM_DEF;
5835 for (arg=0; *args[arg+1]; arg++)
5836 args[arg] = args[arg+1]; // shift args after inversion
5837 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005838
William Lallemand0f99e342011-10-12 17:50:54 +02005839 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5840 strcmp(args[0], "log") != 0) {
5841 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005842 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005843 }
5844
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005845 /* detect section start */
5846 list_for_each_entry(ics, &sections, list) {
5847 if (strcmp(args[0], ics->section_name) == 0) {
5848 cursection = ics->section_name;
5849 cs = ics;
5850 break;
5851 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005852 }
5853
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005855 if (cs)
5856 err_code |= cs->section_parser(file, linenum, args, kwm);
5857 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005858 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005859 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005861
5862 if (err_code & ERR_ABORT)
5863 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005865 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005867 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005868}
5869
Willy Tarreaubb925012009-07-23 13:36:36 +02005870/*
5871 * Returns the error code, 0 if OK, or any combination of :
5872 * - ERR_ABORT: must abort ASAP
5873 * - ERR_FATAL: we can continue parsing but not start the service
5874 * - ERR_WARN: a warning has been emitted
5875 * - ERR_ALERT: an alert has been emitted
5876 * Only the two first ones can stop processing, the two others are just
5877 * indicators.
5878 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005879int check_config_validity()
5880{
5881 int cfgerr = 0;
5882 struct proxy *curproxy = NULL;
5883 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005884 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005885 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005886 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005888 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 /*
5890 * Now, check for the integrity of all that we have collected.
5891 */
5892
5893 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005894 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895
Willy Tarreau193b8c62012-11-22 00:17:38 +01005896 if (!global.tune.max_http_hdr)
5897 global.tune.max_http_hdr = MAX_HTTP_HDR;
5898
5899 if (!global.tune.cookie_len)
5900 global.tune.cookie_len = CAPTURE_LEN;
5901
5902 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5903
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005904 /* Post initialisation of the users and groups lists. */
5905 err_code = userlist_postinit();
5906 if (err_code != ERR_NONE)
5907 goto out;
5908
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005909 /* first, we will invert the proxy list order */
5910 curproxy = NULL;
5911 while (proxy) {
5912 struct proxy *next;
5913
5914 next = proxy->next;
5915 proxy->next = curproxy;
5916 curproxy = proxy;
5917 if (!next)
5918 break;
5919 proxy = next;
5920 }
5921
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005923 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005924 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005925 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005926 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005927 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005928 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005929 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005930
Willy Tarreau050536d2012-10-04 08:47:34 +02005931 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005932 /* proxy ID not set, use automatic numbering with first
5933 * spare entry starting with next_pxid.
5934 */
5935 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5936 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5937 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005938 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005939 next_pxid++;
5940
Willy Tarreau55ea7572007-06-17 19:56:27 +02005941
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005943 /* ensure we don't keep listeners uselessly bound */
5944 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945 curproxy = curproxy->next;
5946 continue;
5947 }
5948
Willy Tarreau102df612014-05-07 23:56:38 +02005949 /* Check multi-process mode compatibility for the current proxy */
5950
5951 if (curproxy->bind_proc) {
5952 /* an explicit bind-process was specified, let's check how many
5953 * processes remain.
5954 */
5955 nbproc = popcount(curproxy->bind_proc);
5956
5957 curproxy->bind_proc &= nbits(global.nbproc);
5958 if (!curproxy->bind_proc && nbproc == 1) {
5959 Warning("Proxy '%s': the process specified on the 'bind-process' directive refers to a process number that is higher than global.nbproc. The proxy has been forced to run on process 1 only.\n", curproxy->id);
5960 curproxy->bind_proc = 1;
5961 }
5962 else if (!curproxy->bind_proc && nbproc > 1) {
5963 Warning("Proxy '%s': all processes specified on the 'bind-process' directive refer to numbers that are all higher than global.nbproc. The directive was ignored and the proxy will run on all processes.\n", curproxy->id);
5964 curproxy->bind_proc = 0;
5965 }
5966 }
5967
Willy Tarreau3d209582014-05-09 17:06:11 +02005968 /* check and reduce the bind-proc of each listener */
5969 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
5970 unsigned long mask;
5971
5972 if (!bind_conf->bind_proc)
5973 continue;
5974
5975 mask = nbits(global.nbproc);
5976 if (curproxy->bind_proc)
5977 mask &= curproxy->bind_proc;
5978 /* mask cannot be null here thanks to the previous checks */
5979
5980 nbproc = popcount(bind_conf->bind_proc);
5981 bind_conf->bind_proc &= mask;
5982
5983 if (!bind_conf->bind_proc && nbproc == 1) {
5984 Warning("Proxy '%s': the process number specified on the 'process' directive of 'bind %s' at [%s:%d] refers to a process not covered by the proxy. This has been fixed by forcing it to run on the proxy's first process only.\n",
5985 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5986 bind_conf->bind_proc = mask & ~(mask - 1);
5987 }
5988 else if (!bind_conf->bind_proc && nbproc > 1) {
5989 Warning("Proxy '%s': the process range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to processes not covered by the proxy. The directive was ignored so that all of the proxy's processes are used.\n",
5990 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
5991 bind_conf->bind_proc = 0;
5992 }
5993 }
5994
Willy Tarreau102df612014-05-07 23:56:38 +02005995 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
5996 * We now check how many processes the proxy will effectively run on.
5997 */
5998
5999 nbproc = global.nbproc;
6000 if (curproxy->bind_proc)
6001 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
6002
6003 if (global.nbproc > 1 && curproxy->table.peers.name) {
6004 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6005 curproxy->id);
6006 cfgerr++;
6007 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006008
Willy Tarreauff01a212009-03-15 13:46:16 +01006009 switch (curproxy->mode) {
6010 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006011 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006012 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006013 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6014 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006015 cfgerr++;
6016 }
6017
6018 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006019 Warning("config : servers will be ignored for %s '%s'.\n",
6020 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006021 break;
6022
6023 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006024 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006025 break;
6026
6027 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006028 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006029 break;
6030 }
6031
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006032 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006033 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006034 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006035 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6036 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006037 cfgerr++;
6038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006040 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006041 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6042 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006043 cfgerr++;
6044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006046 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006047 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6048 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006049 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006050 }
6051 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006052 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006053 /* If no LB algo is set in a backend, and we're not in
6054 * transparent mode, dispatch mode nor proxy mode, we
6055 * want to use balance roundrobin by default.
6056 */
6057 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6058 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
6060 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006061
Willy Tarreau1620ec32011-08-06 17:05:02 +02006062 if (curproxy->options & PR_O_DISPATCH)
6063 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6064 else if (curproxy->options & PR_O_HTTP_PROXY)
6065 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6066 else if (curproxy->options & PR_O_TRANSP)
6067 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006068
Willy Tarreau1620ec32011-08-06 17:05:02 +02006069 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6070 if (curproxy->options & PR_O_DISABLE404) {
6071 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6072 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6073 err_code |= ERR_WARN;
6074 curproxy->options &= ~PR_O_DISABLE404;
6075 }
6076 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6077 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6078 "send-state", proxy_type_str(curproxy), curproxy->id);
6079 err_code |= ERR_WARN;
6080 curproxy->options &= ~PR_O2_CHK_SNDST;
6081 }
Willy Tarreauef781042010-01-27 11:53:01 +01006082 }
6083
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006084 /* if a default backend was specified, let's find it */
6085 if (curproxy->defbe.name) {
6086 struct proxy *target;
6087
Alex Williams96532db2009-11-01 21:27:13 -05006088 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006089 if (!target) {
6090 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6091 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006092 cfgerr++;
6093 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006094 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6095 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006096 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006097 } else {
6098 free(curproxy->defbe.name);
6099 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006100 /* we force the backend to be present on at least all of
6101 * the frontend's processes.
6102 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006103 if (target->bind_proc)
6104 target->bind_proc = curproxy->bind_proc ?
6105 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006106
6107 /* Emit a warning if this proxy also has some servers */
6108 if (curproxy->srv) {
6109 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6110 curproxy->id);
6111 err_code |= ERR_WARN;
6112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
6114 }
6115
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006116 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006117 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6118 /* map jump target for ACT_SETBE in req_rep chain */
6119 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006120 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006121 struct proxy *target;
6122
Willy Tarreaua496b602006-12-17 23:15:24 +01006123 if (exp->action != ACT_SETBE)
6124 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006125
Alex Williams96532db2009-11-01 21:27:13 -05006126 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006127 if (!target) {
6128 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6129 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006130 cfgerr++;
6131 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006132 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6133 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006134 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006135 } else {
6136 free((void *)exp->replace);
6137 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006138 /* we force the backend to be present on at least all of
6139 * the frontend's processes.
6140 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006141 if (target->bind_proc)
6142 target->bind_proc = curproxy->bind_proc ?
6143 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006144 }
6145 }
6146 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006147
6148 /* find the target proxy for 'use_backend' rules */
6149 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006150 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006151 struct logformat_node *node;
6152 char *pxname;
6153
6154 /* Try to parse the string as a log format expression. If the result
6155 * of the parsing is only one entry containing a simple string, then
6156 * it's a standard string corresponding to a static rule, thus the
6157 * parsing is cancelled and be.name is restored to be resolved.
6158 */
6159 pxname = rule->be.name;
6160 LIST_INIT(&rule->be.expr);
6161 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6162 curproxy->conf.args.file, curproxy->conf.args.line);
6163 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6164
6165 if (!LIST_ISEMPTY(&rule->be.expr)) {
6166 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6167 rule->dynamic = 1;
6168 free(pxname);
6169 continue;
6170 }
6171 /* simple string: free the expression and fall back to static rule */
6172 free(node->arg);
6173 free(node);
6174 }
6175
6176 rule->dynamic = 0;
6177 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006178
Alex Williams96532db2009-11-01 21:27:13 -05006179 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006180
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006181 if (!target) {
6182 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6183 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006184 cfgerr++;
6185 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006186 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6187 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006188 cfgerr++;
6189 } else {
6190 free((void *)rule->be.name);
6191 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006192 /* we force the backend to be present on at least all of
6193 * the frontend's processes.
6194 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006195 if (target->bind_proc)
6196 target->bind_proc = curproxy->bind_proc ?
6197 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006198 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006199 }
6200
6201 /* find the target proxy for 'use_backend' rules */
6202 list_for_each_entry(srule, &curproxy->server_rules, list) {
6203 struct server *target = findserver(curproxy, srule->srv.name);
6204
6205 if (!target) {
6206 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6207 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6208 cfgerr++;
6209 continue;
6210 }
6211 free((void *)srule->srv.name);
6212 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006213 }
6214
Emeric Brunb982a3d2010-01-04 15:45:53 +01006215 /* find the target table for 'stick' rules */
6216 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6217 struct proxy *target;
6218
Emeric Brun1d33b292010-01-04 15:47:17 +01006219 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6220 if (mrule->flags & STK_IS_STORE)
6221 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6222
Emeric Brunb982a3d2010-01-04 15:45:53 +01006223 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006224 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006225 else
6226 target = curproxy;
6227
6228 if (!target) {
6229 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6230 curproxy->id, mrule->table.name);
6231 cfgerr++;
6232 }
6233 else if (target->table.size == 0) {
6234 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6235 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6236 cfgerr++;
6237 }
Willy Tarreau12785782012-04-27 21:37:17 +02006238 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6239 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006240 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6241 cfgerr++;
6242 }
6243 else {
6244 free((void *)mrule->table.name);
6245 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006246 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006247 }
6248 }
6249
6250 /* find the target table for 'store response' rules */
6251 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6252 struct proxy *target;
6253
Emeric Brun1d33b292010-01-04 15:47:17 +01006254 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6255
Emeric Brunb982a3d2010-01-04 15:45:53 +01006256 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006257 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006258 else
6259 target = curproxy;
6260
6261 if (!target) {
6262 Alert("Proxy '%s': unable to find store table '%s'.\n",
6263 curproxy->id, mrule->table.name);
6264 cfgerr++;
6265 }
6266 else if (target->table.size == 0) {
6267 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6268 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6269 cfgerr++;
6270 }
Willy Tarreau12785782012-04-27 21:37:17 +02006271 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6272 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006273 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6274 cfgerr++;
6275 }
6276 else {
6277 free((void *)mrule->table.name);
6278 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006279 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006280 }
6281 }
6282
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006283 /* find the target table for 'tcp-request' layer 4 rules */
6284 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6285 struct proxy *target;
6286
Willy Tarreaub4c84932013-07-23 19:15:30 +02006287 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006288 continue;
6289
6290 if (trule->act_prm.trk_ctr.table.n)
6291 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6292 else
6293 target = curproxy;
6294
6295 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006296 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6297 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006298 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006299 cfgerr++;
6300 }
6301 else if (target->table.size == 0) {
6302 Alert("Proxy '%s': table '%s' used but not configured.\n",
6303 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6304 cfgerr++;
6305 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006306 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6307 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6308 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 +01006309 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006310 cfgerr++;
6311 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006312 else {
6313 free(trule->act_prm.trk_ctr.table.n);
6314 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006315 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006316 * to pass a list of counters to track and allocate them right here using
6317 * stktable_alloc_data_type().
6318 */
6319 }
6320 }
6321
Willy Tarreaud1f96522010-08-03 19:34:32 +02006322 /* find the target table for 'tcp-request' layer 6 rules */
6323 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6324 struct proxy *target;
6325
Willy Tarreaub4c84932013-07-23 19:15:30 +02006326 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006327 continue;
6328
6329 if (trule->act_prm.trk_ctr.table.n)
6330 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6331 else
6332 target = curproxy;
6333
6334 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006335 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6336 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006337 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006338 cfgerr++;
6339 }
6340 else if (target->table.size == 0) {
6341 Alert("Proxy '%s': table '%s' used but not configured.\n",
6342 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6343 cfgerr++;
6344 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006345 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6346 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6347 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 +01006348 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006349 cfgerr++;
6350 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006351 else {
6352 free(trule->act_prm.trk_ctr.table.n);
6353 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006354 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006355 * to pass a list of counters to track and allocate them right here using
6356 * stktable_alloc_data_type().
6357 */
6358 }
6359 }
6360
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006361 /* move any "block" rules at the beginning of the http-request rules */
6362 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6363 /* insert block_rules into http_req_rules at the beginning */
6364 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6365 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6366 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6367 curproxy->http_req_rules.n = curproxy->block_rules.n;
6368 LIST_INIT(&curproxy->block_rules);
6369 }
6370
Emeric Brun32da3c42010-09-23 18:39:19 +02006371 if (curproxy->table.peers.name) {
6372 struct peers *curpeers = peers;
6373
6374 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6375 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6376 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006377 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006378 break;
6379 }
6380 }
6381
6382 if (!curpeers) {
6383 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6384 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006385 free((void *)curproxy->table.peers.name);
6386 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006387 cfgerr++;
6388 }
6389 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006390 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6391 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006392 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006393 cfgerr++;
6394 }
6395 }
6396
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006397 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006398 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006399 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6400 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6401 "proxy", curproxy->id);
6402 cfgerr++;
6403 goto out_uri_auth_compat;
6404 }
6405
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006406 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006407 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006408 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006409 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006410
Willy Tarreau95fa4692010-02-01 13:05:50 +01006411 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6412 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006413
6414 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006415 uri_auth_compat_req[i++] = "realm";
6416 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6417 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006418
Willy Tarreau95fa4692010-02-01 13:05:50 +01006419 uri_auth_compat_req[i++] = "unless";
6420 uri_auth_compat_req[i++] = "{";
6421 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6422 uri_auth_compat_req[i++] = "}";
6423 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006424
Willy Tarreauff011f22011-01-06 17:51:27 +01006425 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6426 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006427 cfgerr++;
6428 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006429 }
6430
Willy Tarreauff011f22011-01-06 17:51:27 +01006431 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006432
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006433 if (curproxy->uri_auth->auth_realm) {
6434 free(curproxy->uri_auth->auth_realm);
6435 curproxy->uri_auth->auth_realm = NULL;
6436 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006437
6438 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006439 }
6440out_uri_auth_compat:
6441
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006442 /* compile the log format */
6443 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006444 if (curproxy->conf.logformat_string != default_http_log_format &&
6445 curproxy->conf.logformat_string != default_tcp_log_format &&
6446 curproxy->conf.logformat_string != clf_http_log_format)
6447 free(curproxy->conf.logformat_string);
6448 curproxy->conf.logformat_string = NULL;
6449 free(curproxy->conf.lfs_file);
6450 curproxy->conf.lfs_file = NULL;
6451 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006452 }
6453
Willy Tarreau62a61232013-04-12 18:13:46 +02006454 if (curproxy->conf.logformat_string) {
6455 curproxy->conf.args.ctx = ARGC_LOG;
6456 curproxy->conf.args.file = curproxy->conf.lfs_file;
6457 curproxy->conf.args.line = curproxy->conf.lfs_line;
6458 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006459 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006460 curproxy->conf.args.file = NULL;
6461 curproxy->conf.args.line = 0;
6462 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006463
Willy Tarreau62a61232013-04-12 18:13:46 +02006464 if (curproxy->conf.uniqueid_format_string) {
6465 curproxy->conf.args.ctx = ARGC_UIF;
6466 curproxy->conf.args.file = curproxy->conf.uif_file;
6467 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006468 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006469 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6470 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006471 curproxy->conf.args.file = NULL;
6472 curproxy->conf.args.line = 0;
6473 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006474
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006475 /* only now we can check if some args remain unresolved.
6476 * This must be done after the users and groups resolution.
6477 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006478 cfgerr += smp_resolve_args(curproxy);
6479 if (!cfgerr)
6480 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006481
Willy Tarreau2738a142006-07-08 17:28:09 +02006482 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006483 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006484 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006485 (!curproxy->timeout.connect ||
6486 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006487 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006488 " | While not properly invalid, you will certainly encounter various problems\n"
6489 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006490 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006491 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006492 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006493 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006494
Willy Tarreau1fa31262007-12-03 00:36:16 +01006495 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6496 * We must still support older configurations, so let's find out whether those
6497 * parameters have been set or must be copied from contimeouts.
6498 */
6499 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006500 if (!curproxy->timeout.tarpit ||
6501 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006502 /* tarpit timeout not set. We search in the following order:
6503 * default.tarpit, curr.connect, default.connect.
6504 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006505 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006506 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006507 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006508 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006509 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006510 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006511 }
6512 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006513 (!curproxy->timeout.queue ||
6514 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006515 /* queue timeout not set. We search in the following order:
6516 * default.queue, curr.connect, default.connect.
6517 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006518 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006519 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006520 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006521 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006522 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006523 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006524 }
6525 }
6526
Willy Tarreau1620ec32011-08-06 17:05:02 +02006527 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006528 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6529 curproxy->check_req = (char *)malloc(curproxy->check_len);
6530 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006531 }
6532
Willy Tarreau215663d2014-06-13 18:30:23 +02006533 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6534 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6535 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6536 proxy_type_str(curproxy), curproxy->id);
6537 err_code |= ERR_WARN;
6538 }
6539
Willy Tarreau193b8c62012-11-22 00:17:38 +01006540 /* ensure that cookie capture length is not too large */
6541 if (curproxy->capture_len >= global.tune.cookie_len) {
6542 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6543 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6544 err_code |= ERR_WARN;
6545 curproxy->capture_len = global.tune.cookie_len - 1;
6546 }
6547
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006548 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006549 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006550 curproxy->req_cap_pool = create_pool("ptrcap",
6551 curproxy->nb_req_cap * sizeof(char *),
6552 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006553 }
6554
6555 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006556 curproxy->rsp_cap_pool = create_pool("ptrcap",
6557 curproxy->nb_rsp_cap * sizeof(char *),
6558 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006559 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006560
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561 /* first, we will invert the servers list order */
6562 newsrv = NULL;
6563 while (curproxy->srv) {
6564 struct server *next;
6565
6566 next = curproxy->srv->next;
6567 curproxy->srv->next = newsrv;
6568 newsrv = curproxy->srv;
6569 if (!next)
6570 break;
6571 curproxy->srv = next;
6572 }
6573
Willy Tarreau17edc812014-01-03 12:14:34 +01006574 /* Check that no server name conflicts. This causes trouble in the stats.
6575 * We only emit a warning for the first conflict affecting each server,
6576 * in order to avoid combinatory explosion if all servers have the same
6577 * name. We do that only for servers which do not have an explicit ID,
6578 * because these IDs were made also for distinguishing them and we don't
6579 * want to annoy people who correctly manage them.
6580 */
6581 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6582 struct server *other_srv;
6583
6584 if (newsrv->puid)
6585 continue;
6586
6587 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6588 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6589 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6590 newsrv->conf.file, newsrv->conf.line,
6591 proxy_type_str(curproxy), curproxy->id,
6592 newsrv->id, other_srv->conf.line);
6593 break;
6594 }
6595 }
6596 }
6597
Willy Tarreaudd701652010-05-25 23:03:02 +02006598 /* assign automatic UIDs to servers which don't have one yet */
6599 next_id = 1;
6600 newsrv = curproxy->srv;
6601 while (newsrv != NULL) {
6602 if (!newsrv->puid) {
6603 /* server ID not set, use automatic numbering with first
6604 * spare entry starting with next_svid.
6605 */
6606 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6607 newsrv->conf.id.key = newsrv->puid = next_id;
6608 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6609 }
6610 next_id++;
6611 newsrv = newsrv->next;
6612 }
6613
Willy Tarreau20697042007-11-15 23:26:18 +01006614 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006615 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616
Willy Tarreau62c3be22012-01-20 13:12:32 +01006617 /*
6618 * If this server supports a maxconn parameter, it needs a dedicated
6619 * tasks to fill the emptied slots when a connection leaves.
6620 * Also, resolve deferred tracking dependency if needed.
6621 */
6622 newsrv = curproxy->srv;
6623 while (newsrv != NULL) {
6624 if (newsrv->minconn > newsrv->maxconn) {
6625 /* Only 'minconn' was specified, or it was higher than or equal
6626 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6627 * this will avoid further useless expensive computations.
6628 */
6629 newsrv->maxconn = newsrv->minconn;
6630 } else if (newsrv->maxconn && !newsrv->minconn) {
6631 /* minconn was not specified, so we set it to maxconn */
6632 newsrv->minconn = newsrv->maxconn;
6633 }
6634
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006635#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006636 if (newsrv->use_ssl || newsrv->check.use_ssl)
6637 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006638#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006639
Willy Tarreau2f075e92013-12-03 11:11:34 +01006640 /* set the check type on the server */
6641 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6642
Willy Tarreau62c3be22012-01-20 13:12:32 +01006643 if (newsrv->trackit) {
6644 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006645 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006646 char *pname, *sname;
6647
6648 pname = newsrv->trackit;
6649 sname = strrchr(pname, '/');
6650
6651 if (sname)
6652 *sname++ = '\0';
6653 else {
6654 sname = pname;
6655 pname = NULL;
6656 }
6657
6658 if (pname) {
6659 px = findproxy(pname, PR_CAP_BE);
6660 if (!px) {
6661 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6662 proxy_type_str(curproxy), curproxy->id,
6663 newsrv->id, pname);
6664 cfgerr++;
6665 goto next_srv;
6666 }
6667 } else
6668 px = curproxy;
6669
6670 srv = findserver(px, sname);
6671 if (!srv) {
6672 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6673 proxy_type_str(curproxy), curproxy->id,
6674 newsrv->id, sname);
6675 cfgerr++;
6676 goto next_srv;
6677 }
6678
Willy Tarreau32091232014-05-16 13:52:00 +02006679 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6680 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6681 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006682 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006683 "tracking as it does not have any check nor agent enabled.\n",
6684 proxy_type_str(curproxy), curproxy->id,
6685 newsrv->id, px->id, srv->id);
6686 cfgerr++;
6687 goto next_srv;
6688 }
6689
6690 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6691
6692 if (loop) {
6693 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6694 "belongs to a tracking chain looping back to %s/%s.\n",
6695 proxy_type_str(curproxy), curproxy->id,
6696 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006697 cfgerr++;
6698 goto next_srv;
6699 }
6700
6701 if (curproxy != px &&
6702 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6703 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6704 "tracking: disable-on-404 option inconsistency.\n",
6705 proxy_type_str(curproxy), curproxy->id,
6706 newsrv->id, px->id, srv->id);
6707 cfgerr++;
6708 goto next_srv;
6709 }
6710
6711 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006712 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006713 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006714 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006715 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006716 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006717 }
6718
6719 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006720 newsrv->tracknext = srv->trackers;
6721 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006722
6723 free(newsrv->trackit);
6724 newsrv->trackit = NULL;
6725 }
6726 next_srv:
6727 newsrv = newsrv->next;
6728 }
6729
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006730 /* We have to initialize the server lookup mechanism depending
6731 * on what LB algorithm was choosen.
6732 */
6733
6734 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6735 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6736 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006737 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6738 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6739 init_server_map(curproxy);
6740 } else {
6741 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6742 fwrr_init_server_groups(curproxy);
6743 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006744 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006745
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006746 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006747 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6748 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6749 fwlc_init_server_tree(curproxy);
6750 } else {
6751 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6752 fas_init_server_tree(curproxy);
6753 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006754 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006755
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006756 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006757 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6758 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6759 chash_init_server_tree(curproxy);
6760 } else {
6761 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6762 init_server_map(curproxy);
6763 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006764 break;
6765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006766
6767 if (curproxy->options & PR_O_LOGASAP)
6768 curproxy->to_log &= ~LW_BYTES;
6769
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006770 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006771 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006772 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6773 proxy_type_str(curproxy), curproxy->id);
6774 err_code |= ERR_WARN;
6775 }
6776
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006777 if (curproxy->mode != PR_MODE_HTTP) {
6778 int optnum;
6779
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006780 if (curproxy->uri_auth) {
6781 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6782 proxy_type_str(curproxy), curproxy->id);
6783 err_code |= ERR_WARN;
6784 curproxy->uri_auth = NULL;
6785 }
6786
Willy Tarreau87cf5142011-08-19 22:57:24 +02006787 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006788 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6789 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6790 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006791 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006792 }
6793
6794 if (curproxy->options & PR_O_ORGTO) {
6795 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6796 "originalto", proxy_type_str(curproxy), curproxy->id);
6797 err_code |= ERR_WARN;
6798 curproxy->options &= ~PR_O_ORGTO;
6799 }
6800
6801 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6802 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6803 (curproxy->cap & cfg_opts[optnum].cap) &&
6804 (curproxy->options & cfg_opts[optnum].val)) {
6805 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6806 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6807 err_code |= ERR_WARN;
6808 curproxy->options &= ~cfg_opts[optnum].val;
6809 }
6810 }
6811
6812 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6813 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6814 (curproxy->cap & cfg_opts2[optnum].cap) &&
6815 (curproxy->options2 & cfg_opts2[optnum].val)) {
6816 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6817 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6818 err_code |= ERR_WARN;
6819 curproxy->options2 &= ~cfg_opts2[optnum].val;
6820 }
6821 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006822
Pieter Baauwd551fb52013-05-08 22:49:23 +02006823#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006824 if (curproxy->conn_src.bind_hdr_occ) {
6825 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006826 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006827 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006828 err_code |= ERR_WARN;
6829 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006830#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006831 }
6832
Willy Tarreaubaaee002006-06-26 02:48:02 +02006833 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006834 * ensure that we're not cross-dressing a TCP server into HTTP.
6835 */
6836 newsrv = curproxy->srv;
6837 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006838 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006839 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6840 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006841 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006842 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006843
Willy Tarreau0cec3312011-10-31 13:49:26 +01006844 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6845 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6846 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6847 err_code |= ERR_WARN;
6848 }
6849
Willy Tarreauc93cd162014-05-13 15:54:22 +02006850 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006851 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6852 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6853 err_code |= ERR_WARN;
6854 }
6855
Pieter Baauwd551fb52013-05-08 22:49:23 +02006856#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006857 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6858 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006859 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 +01006860 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006861 err_code |= ERR_WARN;
6862 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006863#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006864 newsrv = newsrv->next;
6865 }
6866
Willy Tarreauc1a21672009-08-16 22:37:44 +02006867 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006868 if (!curproxy->accept)
6869 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006870
Willy Tarreauc1a21672009-08-16 22:37:44 +02006871 if (curproxy->tcp_req.inspect_delay ||
6872 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006873 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006874
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006875 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006876 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006877 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006878 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006879
6880 /* both TCP and HTTP must check switching rules */
6881 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6882 }
6883
6884 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006885 if (curproxy->tcp_req.inspect_delay ||
6886 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6887 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6888
Emeric Brun97679e72010-09-23 17:56:44 +02006889 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6890 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6891
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006892 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006893 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006894 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006895 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006896
6897 /* If the backend does requires RDP cookie persistence, we have to
6898 * enable the corresponding analyser.
6899 */
6900 if (curproxy->options2 & PR_O2_RDPC_PRST)
6901 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6902 }
6903
Emeric Brunc52962f2012-11-15 18:28:02 +01006904#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006905 /* Configure SSL for each bind line.
6906 * Note: if configuration fails at some point, the ->ctx member
6907 * remains NULL so that listeners can later detach.
6908 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006909 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006910 int alloc_ctx;
6911
Emeric Brunc52962f2012-11-15 18:28:02 +01006912 if (!bind_conf->is_ssl) {
6913 if (bind_conf->default_ctx) {
6914 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6915 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6916 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006917 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006918 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006919 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006920 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006921 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006922 cfgerr++;
6923 continue;
6924 }
6925
Emeric Brun8dc60392014-05-09 13:52:00 +02006926 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006927 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02006928 if (alloc_ctx == SHCTX_E_INIT_LOCK)
6929 Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
6930 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02006931 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02006932 cfgerr++;
6933 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006934 }
6935
Emeric Brunfc0421f2012-09-07 17:30:07 +02006936 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006937 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006938 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006939#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006940
Willy Tarreaue6b98942007-10-29 01:09:36 +01006941 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006942 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006943 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006944 if (!listener->luid) {
6945 /* listener ID not set, use automatic numbering with first
6946 * spare entry starting with next_luid.
6947 */
6948 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6949 listener->conf.id.key = listener->luid = next_id;
6950 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006951 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006952 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006953
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006954 /* enable separate counters */
6955 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6956 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006957 if (!listener->name)
6958 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006959 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006960
Willy Tarreaue6b98942007-10-29 01:09:36 +01006961 if (curproxy->options & PR_O_TCP_NOLING)
6962 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006963 if (!listener->maxconn)
6964 listener->maxconn = curproxy->maxconn;
6965 if (!listener->backlog)
6966 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006967 if (!listener->maxaccept)
6968 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6969
6970 /* we want to have an optimal behaviour on single process mode to
6971 * maximize the work at once, but in multi-process we want to keep
6972 * some fairness between processes, so we target half of the max
6973 * number of events to be balanced over all the processes the proxy
6974 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6975 * used to disable the limit.
6976 */
6977 if (listener->maxaccept > 0) {
6978 if (nbproc > 1)
6979 listener->maxaccept = (listener->maxaccept + 1) / 2;
6980 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6981 }
6982
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006983 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006984 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006985 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006986 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006987
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006988 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6989 listener->options |= LI_O_TCP_RULES;
6990
Willy Tarreaude3041d2010-05-31 10:56:17 +02006991 if (curproxy->mon_mask.s_addr)
6992 listener->options |= LI_O_CHK_MONNET;
6993
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006994 /* smart accept mode is automatic in HTTP mode */
6995 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006996 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006997 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6998 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006999 }
7000
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007001 /* Release unused SSL configs */
7002 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7003 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007004 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007005#ifdef USE_OPENSSL
7006 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007007 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007008 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007009 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007010 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007011#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007012 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007013
Willy Tarreau102df612014-05-07 23:56:38 +02007014 if (nbproc > 1) {
7015 if (curproxy->uri_auth) {
7016 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7017 curproxy->id);
7018 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7019 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7020 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007021 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007022 }
Willy Tarreau102df612014-05-07 23:56:38 +02007023 if (curproxy->appsession_name) {
7024 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7025 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007026 }
Willy Tarreau102df612014-05-07 23:56:38 +02007027 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7028 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7029 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007030 }
7031 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007032
7033 /* create the task associated with the proxy */
7034 curproxy->task = task_new();
7035 if (curproxy->task) {
7036 curproxy->task->context = curproxy;
7037 curproxy->task->process = manage_proxy;
7038 /* no need to queue, it will be done automatically if some
7039 * listener gets limited.
7040 */
7041 curproxy->task->expire = TICK_ETERNITY;
7042 } else {
7043 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7044 curproxy->id);
7045 cfgerr++;
7046 }
7047
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048 curproxy = curproxy->next;
7049 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007050
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007051 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02007052 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02007053 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7054 unsigned long mask;
7055
7056 mask = nbits(global.nbproc);
7057 if (global.stats_fe->bind_proc)
7058 mask &= global.stats_fe->bind_proc;
7059
7060 if (bind_conf->bind_proc)
7061 mask &= bind_conf->bind_proc;
7062
7063 /* stop here if more than one process is used */
7064 if (popcount(mask) > 1)
7065 break;
7066 }
7067 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7068 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007069 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007070 }
7071
7072 /* automatically compute fullconn if not set. We must not do it in the
7073 * loop above because cross-references are not yet fully resolved.
7074 */
7075 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7076 /* If <fullconn> is not set, let's set it to 10% of the sum of
7077 * the possible incoming frontend's maxconns.
7078 */
7079 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7080 struct proxy *fe;
7081 int total = 0;
7082
7083 /* sum up the number of maxconns of frontends which
7084 * reference this backend at least once or which are
7085 * the same one ('listen').
7086 */
7087 for (fe = proxy; fe; fe = fe->next) {
7088 struct switching_rule *rule;
7089 struct hdr_exp *exp;
7090 int found = 0;
7091
7092 if (!(fe->cap & PR_CAP_FE))
7093 continue;
7094
7095 if (fe == curproxy) /* we're on a "listen" instance */
7096 found = 1;
7097
7098 if (fe->defbe.be == curproxy) /* "default_backend" */
7099 found = 1;
7100
7101 /* check if a "use_backend" rule matches */
7102 if (!found) {
7103 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007104 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007105 found = 1;
7106 break;
7107 }
7108 }
7109 }
7110
7111 /* check if a "reqsetbe" rule matches */
7112 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7113 if (exp->action == ACT_SETBE &&
7114 (struct proxy *)exp->replace == curproxy) {
7115 found = 1;
7116 break;
7117 }
7118 }
7119
7120 /* now we've checked all possible ways to reference a backend
7121 * from a frontend.
7122 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007123 if (!found)
7124 continue;
7125 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007126 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007127 /* we have the sum of the maxconns in <total>. We only
7128 * keep 10% of that sum to set the default fullconn, with
7129 * a hard minimum of 1 (to avoid a divide by zero).
7130 */
7131 curproxy->fullconn = (total + 9) / 10;
7132 if (!curproxy->fullconn)
7133 curproxy->fullconn = 1;
7134 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007135 }
7136
Willy Tarreau056f5682010-06-06 15:51:11 +02007137 /* initialize stick-tables on backend capable proxies. This must not
7138 * be done earlier because the data size may be discovered while parsing
7139 * other proxies.
7140 */
Godbach9703e662013-12-11 21:11:41 +08007141 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007142 if (curproxy->state == PR_STSTOPPED)
7143 continue;
7144
Godbach9703e662013-12-11 21:11:41 +08007145 if (!stktable_init(&curproxy->table)) {
7146 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7147 cfgerr++;
7148 }
7149 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007150
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007151 /*
7152 * Recount currently required checks.
7153 */
7154
7155 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7156 int optnum;
7157
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007158 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7159 if (curproxy->options & cfg_opts[optnum].val)
7160 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007161
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007162 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7163 if (curproxy->options2 & cfg_opts2[optnum].val)
7164 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007165 }
7166
Willy Tarreau122541c2011-09-07 21:24:49 +02007167 if (peers) {
7168 struct peers *curpeers = peers, **last;
7169 struct peer *p, *pb;
7170
7171 /* Remove all peers sections which don't have a valid listener.
7172 * This can happen when a peers section is never referenced and
7173 * does not contain a local peer.
7174 */
7175 last = &peers;
7176 while (*last) {
7177 curpeers = *last;
7178 if (curpeers->peers_fe) {
7179 last = &curpeers->next;
7180 continue;
7181 }
7182
7183 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7184 curpeers->id, localpeer);
7185
7186 p = curpeers->remote;
7187 while (p) {
7188 pb = p->next;
7189 free(p->id);
7190 free(p);
7191 p = pb;
7192 }
7193
7194 /* Destroy and unlink this curpeers section.
7195 * Note: curpeers is backed up into *last.
7196 */
7197 free(curpeers->id);
7198 curpeers = curpeers->next;
7199 free(*last);
7200 *last = curpeers;
7201 }
7202 }
7203
Willy Tarreau34eb6712011-10-24 18:15:04 +02007204 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007205 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007206 MEM_F_SHARED);
7207
Willy Tarreaubb925012009-07-23 13:36:36 +02007208 if (cfgerr > 0)
7209 err_code |= ERR_ALERT | ERR_FATAL;
7210 out:
7211 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007212}
7213
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007214/*
7215 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7216 * parsing sessions.
7217 */
7218void cfg_register_keywords(struct cfg_kw_list *kwl)
7219{
7220 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7221}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007222
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007223/*
7224 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7225 */
7226void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7227{
7228 LIST_DEL(&kwl->list);
7229 LIST_INIT(&kwl->list);
7230}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007231
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007232/* this function register new section in the haproxy configuration file.
7233 * <section_name> is the name of this new section and <section_parser>
7234 * is the called parser. If two section declaration have the same name,
7235 * only the first declared is used.
7236 */
7237int cfg_register_section(char *section_name,
7238 int (*section_parser)(const char *, int, char **, int))
7239{
7240 struct cfg_section *cs;
7241
7242 cs = calloc(1, sizeof(*cs));
7243 if (!cs) {
7244 Alert("register section '%s': out of memory.\n", section_name);
7245 return 0;
7246 }
7247
7248 cs->section_name = section_name;
7249 cs->section_parser = section_parser;
7250
7251 LIST_ADDQ(&sections, &cs->list);
7252
7253 return 1;
7254}
7255
Willy Tarreaubaaee002006-06-26 02:48:02 +02007256/*
7257 * Local variables:
7258 * c-indent-level: 8
7259 * c-basic-offset: 8
7260 * End:
7261 */