blob: 53b136a36a63f6e1f9c1ef64ca954d43af4f0db6 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100113/* permit to store configuration section */
114struct cfg_section {
115 struct list list;
116 char *section_name;
117 int (*section_parser)(const char *, int, char **, int);
118};
119
120/* Used to chain configuration sections definitions. This list
121 * stores struct cfg_section
122 */
123struct list sections = LIST_HEAD_INIT(sections);
124
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100126struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127 const char *name;
128 unsigned int val;
129 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100130 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100132};
133
134/* proxy->options */
135static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
138 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
139 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
140 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
141 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
142 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100144 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
146 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
147 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
148 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
149 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100150#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100152#else
153 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100154#endif
155
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100157};
158
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159/* proxy->options2 */
160static const struct cfg_opt cfg_opts2[] =
161{
162#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
165 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "splice-request", 0, 0, 0, 0 },
168 { "splice-response", 0, 0, 0, 0 },
169 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
172 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
173 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
174 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
175 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
176 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
177 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
178 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
179 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400180 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200182 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200183 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184 { NULL, 0, 0, 0 }
185};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186
Willy Tarreau6daf3432008-01-22 16:44:08 +0100187static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
189int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100190int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200192/* List head of all known configuration keywords */
193static struct cfg_kw_list cfg_keywords = {
194 .list = LIST_HEAD_INIT(cfg_keywords.list)
195};
196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197/*
198 * converts <str> to a list of listeners which are dynamically allocated.
199 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
200 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
201 * - <port> is a numerical port from 1 to 65535 ;
202 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
203 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200204 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
205 * not NULL, it must be a valid pointer to either NULL or a freeable area that
206 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200208int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209{
210 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 int port, end;
213
214 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100218 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
220 str = next;
221 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100222 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 *next++ = 0;
224 }
225
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100226 ss2 = str2sa_range(str, &port, &end, err,
227 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
228 if (!ss2)
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100232 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200233 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100237 if (!port || !end) {
238 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
239 goto fail;
240 }
241
Emeric Bruned760922010-10-22 17:59:25 +0200242 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200244 goto fail;
245 }
246
247 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100252 else if (ss2->ss_family == AF_UNSPEC) {
253 socklen_t addr_len;
254
255 /* We want to attach to an already bound fd whose number
256 * is in the addr part of ss2 when cast to sockaddr_in.
257 * Note that by definition there is a single listener.
258 * We still have to determine the address family to
259 * register the correct protocol.
260 */
261 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
262 addr_len = sizeof(*ss2);
263 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
264 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
265 goto fail;
266 }
267
268 port = end = get_host_port(ss2);
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100271 /* OK the address looks correct */
272 ss = *ss2;
273
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 for (; port <= end; port++) {
275 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100276 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200277 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
278 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
279 l->frontend = curproxy;
280 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200284 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 l->state = LI_INIT;
286
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100287 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 tcpv4_add_listener(l);
290 }
Emeric Bruned760922010-10-22 17:59:25 +0200291 else if (ss.ss_family == AF_INET6) {
292 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
293 tcpv6_add_listener(l);
294 }
295 else {
Emeric Bruned760922010-10-22 17:59:25 +0200296 uxst_add_listener(l);
297 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200299 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 } /* end for(port) */
302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
Willy Tarreau61d18892009-03-31 10:49:21 +0200310/* Report a warning if a rule is placed after a 'block' rule.
311 * Return 1 if the warning has been emitted, otherwise 0.
312 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100313int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200314{
315 if (!LIST_ISEMPTY(&proxy->block_cond)) {
316 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
317 file, line, arg);
318 return 1;
319 }
320 return 0;
321}
322
323/* Report a warning if a rule is placed after a reqrewrite rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200327{
328 if (proxy->req_exp) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
336/* Report a warning if a rule is placed after a reqadd rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100341 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a redirect rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
354 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a 'use_backend' rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
378 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
379 warnif_rule_after_reqadd(proxy, file, line, arg) ||
380 warnif_rule_after_redirect(proxy, file, line, arg) ||
381 warnif_rule_after_use_backend(proxy, file, line, arg);
382}
383
384/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100385int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200386{
387 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100399/* Report it if a request ACL condition uses some keywords that are incompatible
400 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
401 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
402 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100403 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100404static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100405{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100406 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200407 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100408
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100409 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100410 return 0;
411
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100412 acl = acl_cond_conflicts(cond, where);
413 if (acl) {
414 if (acl->name && *acl->name)
415 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
416 file, line, acl->name, sample_ckp_names(where));
417 else
418 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200419 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100420 return ERR_WARN;
421 }
422 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100423 return 0;
424
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100425 if (acl->name && *acl->name)
426 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200427 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100428 else
429 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200430 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100431 return ERR_WARN;
432}
433
Willy Tarreaubaaee002006-06-26 02:48:02 +0200434/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200435 * parse a line in a <global> section. Returns the error code, 0 if OK, or
436 * any combination of :
437 * - ERR_ABORT: must abort ASAP
438 * - ERR_FATAL: we can continue parsing but not start the service
439 * - ERR_WARN: a warning has been emitted
440 * - ERR_ALERT: an alert has been emitted
441 * Only the two first ones can stop processing, the two others are just
442 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200444int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200445{
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200447 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200448
449 if (!strcmp(args[0], "global")) { /* new section */
450 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200453 else if (!strcmp(args[0], "ca-base")) {
454#ifdef USE_OPENSSL
455 if (global.ca_base != NULL) {
456 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
457 err_code |= ERR_ALERT;
458 goto out;
459 }
460 if (*(args[1]) == 0) {
461 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
462 err_code |= ERR_ALERT | ERR_FATAL;
463 goto out;
464 }
465 global.ca_base = strdup(args[1]);
466#else
467 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
468 err_code |= ERR_ALERT | ERR_FATAL;
469 goto out;
470#endif
471 }
472 else if (!strcmp(args[0], "crt-base")) {
473#ifdef USE_OPENSSL
474 if (global.crt_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.crt_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491 else if (!strcmp(args[0], "daemon")) {
492 global.mode |= MODE_DAEMON;
493 }
494 else if (!strcmp(args[0], "debug")) {
495 global.mode |= MODE_DEBUG;
496 }
497 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100498 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200500 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100501 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100504 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100506 else if (!strcmp(args[0], "nosplice")) {
507 global.tune.options &= ~GTUNE_USE_SPLICE;
508 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200509 else if (!strcmp(args[0], "nogetaddrinfo")) {
510 global.tune.options &= ~GTUNE_USE_GAI;
511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200512 else if (!strcmp(args[0], "quiet")) {
513 global.mode |= MODE_QUIET;
514 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200515 else if (!strcmp(args[0], "tune.maxpollevents")) {
516 if (global.tune.maxpollevents != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200518 err_code |= ERR_ALERT;
519 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200525 }
526 global.tune.maxpollevents = atol(args[1]);
527 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100528 else if (!strcmp(args[0], "tune.maxaccept")) {
529 if (global.tune.maxaccept != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 err_code |= ERR_ALERT;
532 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100538 }
539 global.tune.maxaccept = atol(args[1]);
540 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200541 else if (!strcmp(args[0], "tune.chksize")) {
542 if (*(args[1]) == 0) {
543 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
546 }
547 global.tune.chksize = atol(args[1]);
548 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200549#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100550 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 global.tune.sslcachesize = atol(args[1]);
557 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100558 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
559 unsigned int ssllifetime;
560 const char *res;
561
562 if (*(args[1]) == 0) {
563 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566 }
567
568 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
569 if (res) {
570 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
571 file, linenum, *res, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575
576 global.tune.ssllifetime = ssllifetime;
577 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100578 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
579 if (*(args[1]) == 0) {
580 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT | ERR_FATAL;
582 goto out;
583 }
584 global.tune.ssl_max_record = atol(args[1]);
585 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200586#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200587 else if (!strcmp(args[0], "tune.bufsize")) {
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
592 }
593 global.tune.bufsize = atol(args[1]);
594 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
595 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100596 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100597 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200598 }
599 else if (!strcmp(args[0], "tune.maxrewrite")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.maxrewrite = atol(args[1]);
606 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
607 global.tune.maxrewrite = global.tune.bufsize / 2;
608 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100609 else if (!strcmp(args[0], "tune.idletimer")) {
610 unsigned int idle;
611 const char *res;
612
613 if (*(args[1]) == 0) {
614 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT | ERR_FATAL;
616 goto out;
617 }
618
619 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
620 if (res) {
621 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
622 file, linenum, *res, args[0]);
623 err_code |= ERR_ALERT | ERR_FATAL;
624 goto out;
625 }
626
627 if (idle > 65535) {
628 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631 }
632 global.tune.idle_timer = idle;
633 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100634 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
635 if (global.tune.client_rcvbuf != 0) {
636 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT;
638 goto out;
639 }
640 if (*(args[1]) == 0) {
641 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
642 err_code |= ERR_ALERT | ERR_FATAL;
643 goto out;
644 }
645 global.tune.client_rcvbuf = atol(args[1]);
646 }
647 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
648 if (global.tune.server_rcvbuf != 0) {
649 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT;
651 goto out;
652 }
653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.server_rcvbuf = atol(args[1]);
659 }
660 else if (!strcmp(args[0], "tune.sndbuf.client")) {
661 if (global.tune.client_sndbuf != 0) {
662 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT;
664 goto out;
665 }
666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
670 }
671 global.tune.client_sndbuf = atol(args[1]);
672 }
673 else if (!strcmp(args[0], "tune.sndbuf.server")) {
674 if (global.tune.server_sndbuf != 0) {
675 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT;
677 goto out;
678 }
679 if (*(args[1]) == 0) {
680 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
681 err_code |= ERR_ALERT | ERR_FATAL;
682 goto out;
683 }
684 global.tune.server_sndbuf = atol(args[1]);
685 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200686 else if (!strcmp(args[0], "tune.pipesize")) {
687 if (*(args[1]) == 0) {
688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
691 }
692 global.tune.pipesize = atol(args[1]);
693 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100694 else if (!strcmp(args[0], "tune.http.cookielen")) {
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
699 }
700 global.tune.cookie_len = atol(args[1]) + 1;
701 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200702 else if (!strcmp(args[0], "tune.http.maxhdr")) {
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.max_http_hdr = atol(args[1]);
709 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100710 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
711#ifdef USE_ZLIB
712 if (*args[1]) {
713 global.tune.zlibmemlevel = atoi(args[1]);
714 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
715 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
716 file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 } else {
721 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
722 file, linenum, args[0]);
723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
725 }
726#else
727 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730#endif
731 }
732 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
733#ifdef USE_ZLIB
734 if (*args[1]) {
735 global.tune.zlibwindowsize = atoi(args[1]);
736 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
737 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
738 file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 } else {
743 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
744 file, linenum, args[0]);
745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
747 }
748#else
749 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
752#endif
753 }
William Lallemandf3747832012-11-09 12:33:10 +0100754 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
755 if (*args[1]) {
756 global.tune.comp_maxlevel = atoi(args[1]);
757 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
758 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
759 file, linenum, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 } else {
764 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
765 file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 else if (!strcmp(args[0], "uid")) {
771 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200772 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
781 global.uid = atol(args[1]);
782 }
783 else if (!strcmp(args[0], "gid")) {
784 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200786 err_code |= ERR_ALERT;
787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788 }
789 if (*(args[1]) == 0) {
790 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 }
794 global.gid = atol(args[1]);
795 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200796 /* user/group name handling */
797 else if (!strcmp(args[0], "user")) {
798 struct passwd *ha_user;
799 if (global.uid != 0) {
800 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200801 err_code |= ERR_ALERT;
802 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200803 }
804 errno = 0;
805 ha_user = getpwnam(args[1]);
806 if (ha_user != NULL) {
807 global.uid = (int)ha_user->pw_uid;
808 }
809 else {
810 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200811 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200812 }
813 }
814 else if (!strcmp(args[0], "group")) {
815 struct group *ha_group;
816 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200817 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200818 err_code |= ERR_ALERT;
819 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200820 }
821 errno = 0;
822 ha_group = getgrnam(args[1]);
823 if (ha_group != NULL) {
824 global.gid = (int)ha_group->gr_gid;
825 }
826 else {
827 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200828 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200829 }
830 }
831 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 if (*(args[1]) == 0) {
834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 }
838 global.nbproc = atol(args[1]);
839 }
840 else if (!strcmp(args[0], "maxconn")) {
841 if (global.maxconn != 0) {
842 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT;
844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 }
846 if (*(args[1]) == 0) {
847 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200848 err_code |= ERR_ALERT | ERR_FATAL;
849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200850 }
851 global.maxconn = atol(args[1]);
852#ifdef SYSTEM_MAXCONN
853 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
854 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
855 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200856 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858#endif /* SYSTEM_MAXCONN */
859 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200860 else if (!strcmp(args[0], "maxsslconn")) {
861#ifdef USE_OPENSSL
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 global.maxsslconn = atol(args[1]);
868#else
Emeric Brun0914df82012-10-02 18:45:42 +0200869 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200872#endif
873 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100874 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
875#ifdef USE_OPENSSL
876 if (*(args[1]) == 0) {
877 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 free(global.listen_default_ciphers);
882 global.listen_default_ciphers = strdup(args[1]);
883#else
884 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887#endif
888 }
889 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
890#ifdef USE_OPENSSL
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
896 free(global.connect_default_ciphers);
897 global.connect_default_ciphers = strdup(args[1]);
898#else
899 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902#endif
903 }
Emeric Brun850efd52014-01-29 12:24:34 +0100904 else if (!strcmp(args[0], "ssl-server-verify")) {
905 if (*(args[1]) == 0) {
906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910 if (strcmp(args[1],"none") == 0)
911 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
912 else if (strcmp(args[1],"required") == 0)
913 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
914 else {
915 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200920 else if (!strcmp(args[0], "maxconnrate")) {
921 if (global.cps_lim != 0) {
922 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
923 err_code |= ERR_ALERT;
924 goto out;
925 }
926 if (*(args[1]) == 0) {
927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 global.cps_lim = atol(args[1]);
932 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200933 else if (!strcmp(args[0], "maxsessrate")) {
934 if (global.sps_lim != 0) {
935 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT;
937 goto out;
938 }
939 if (*(args[1]) == 0) {
940 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944 global.sps_lim = atol(args[1]);
945 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200946 else if (!strcmp(args[0], "maxsslrate")) {
947 if (global.ssl_lim != 0) {
948 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT;
950 goto out;
951 }
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957 global.ssl_lim = atol(args[1]);
958 }
William Lallemandd85f9172012-11-09 17:05:39 +0100959 else if (!strcmp(args[0], "maxcomprate")) {
960 if (*(args[1]) == 0) {
961 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 global.comp_rate_lim = atoi(args[1]) * 1024;
966 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100967 else if (!strcmp(args[0], "maxpipes")) {
968 if (global.maxpipes != 0) {
969 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200970 err_code |= ERR_ALERT;
971 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100972 }
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100977 }
978 global.maxpipes = atol(args[1]);
979 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100980 else if (!strcmp(args[0], "maxzlibmem")) {
981 if (*(args[1]) == 0) {
982 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
William Lallemande3a7d992012-11-20 11:25:20 +0100986 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100987 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100988 else if (!strcmp(args[0], "maxcompcpuusage")) {
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100995 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100996 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000}
1001
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 else if (!strcmp(args[0], "ulimit-n")) {
1003 if (global.rlimit_nofile != 0) {
1004 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT;
1006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 }
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 }
1013 global.rlimit_nofile = atol(args[1]);
1014 }
1015 else if (!strcmp(args[0], "chroot")) {
1016 if (global.chroot != NULL) {
1017 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT;
1019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 }
1026 global.chroot = strdup(args[1]);
1027 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001028 else if (!strcmp(args[0], "description")) {
1029 int i, len=0;
1030 char *d;
1031
1032 if (!*args[1]) {
1033 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1034 file, linenum, args[0]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037 }
1038
Willy Tarreau348acfe2014-04-14 15:00:39 +02001039 for (i = 1; *args[i]; i++)
1040 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001041
1042 if (global.desc)
1043 free(global.desc);
1044
1045 global.desc = d = (char *)calloc(1, len);
1046
Willy Tarreau348acfe2014-04-14 15:00:39 +02001047 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1048 for (i = 2; *args[i]; i++)
1049 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001050 }
1051 else if (!strcmp(args[0], "node")) {
1052 int i;
1053 char c;
1054
1055 for (i=0; args[1][i]; i++) {
1056 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001057 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1058 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001059 break;
1060 }
1061
1062 if (!i || args[1][i]) {
1063 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1064 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1065 file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069
1070 if (global.node)
1071 free(global.node);
1072
1073 global.node = strdup(args[1]);
1074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 else if (!strcmp(args[0], "pidfile")) {
1076 if (global.pidfile != NULL) {
1077 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT;
1079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081 if (*(args[1]) == 0) {
1082 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 }
1086 global.pidfile = strdup(args[1]);
1087 }
Emeric Bruned760922010-10-22 17:59:25 +02001088 else if (!strcmp(args[0], "unix-bind")) {
1089 int cur_arg = 1;
1090 while (*(args[cur_arg])) {
1091 if (!strcmp(args[cur_arg], "prefix")) {
1092 if (global.unix_bind.prefix != NULL) {
1093 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1094 err_code |= ERR_ALERT;
1095 cur_arg += 2;
1096 continue;
1097 }
1098
1099 if (*(args[cur_arg+1]) == 0) {
1100 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
1104 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1105 cur_arg += 2;
1106 continue;
1107 }
1108
1109 if (!strcmp(args[cur_arg], "mode")) {
1110
1111 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1112 cur_arg += 2;
1113 continue;
1114 }
1115
1116 if (!strcmp(args[cur_arg], "uid")) {
1117
1118 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1119 cur_arg += 2;
1120 continue;
1121 }
1122
1123 if (!strcmp(args[cur_arg], "gid")) {
1124
1125 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1126 cur_arg += 2;
1127 continue;
1128 }
1129
1130 if (!strcmp(args[cur_arg], "user")) {
1131 struct passwd *user;
1132
1133 user = getpwnam(args[cur_arg + 1]);
1134 if (!user) {
1135 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1136 file, linenum, args[0], args[cur_arg + 1 ]);
1137 err_code |= ERR_ALERT | ERR_FATAL;
1138 goto out;
1139 }
1140
1141 global.unix_bind.ux.uid = user->pw_uid;
1142 cur_arg += 2;
1143 continue;
1144 }
1145
1146 if (!strcmp(args[cur_arg], "group")) {
1147 struct group *group;
1148
1149 group = getgrnam(args[cur_arg + 1]);
1150 if (!group) {
1151 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1152 file, linenum, args[0], args[cur_arg + 1 ]);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto out;
1155 }
1156
1157 global.unix_bind.ux.gid = group->gr_gid;
1158 cur_arg += 2;
1159 continue;
1160 }
1161
Willy Tarreaub48f9582011-09-05 01:17:06 +02001162 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001163 file, linenum, args[0]);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
1166 }
1167 }
William Lallemand0f99e342011-10-12 17:50:54 +02001168 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1169 /* delete previous herited or defined syslog servers */
1170 struct logsrv *back;
1171 struct logsrv *tmp;
1172
1173 if (*(args[1]) != 0) {
1174 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
1177 }
1178
1179 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1180 LIST_DEL(&tmp->list);
1181 free(tmp);
1182 }
1183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001185 struct sockaddr_storage *sk;
1186 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001187 struct logsrv *logsrv;
1188
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 if (*(args[1]) == 0 || *(args[2]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
William Lallemand0f99e342011-10-12 17:50:54 +02001194
1195 logsrv = calloc(1, sizeof(struct logsrv));
1196
1197 logsrv->facility = get_log_facility(args[2]);
1198 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001201 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203
William Lallemand0f99e342011-10-12 17:50:54 +02001204 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001206 logsrv->level = get_log_level(args[3]);
1207 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001209 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001210 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 }
1212 }
1213
William Lallemand0f99e342011-10-12 17:50:54 +02001214 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001215 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001216 logsrv->minlvl = get_log_level(args[4]);
1217 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001218 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001219 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001220 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001221 }
1222 }
1223
Willy Tarreau902636f2013-03-10 19:44:48 +01001224 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001225 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001226 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001227 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001228 free(logsrv);
1229 goto out;
1230 }
1231 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001232
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001233 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001234 if (port1 != port2) {
1235 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1236 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001237 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001238 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001239 goto out;
1240 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001241
William Lallemand0f99e342011-10-12 17:50:54 +02001242 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001243 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001244 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246
William Lallemand0f99e342011-10-12 17:50:54 +02001247 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001248 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001249 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1250 char *name;
1251 int len;
1252
1253 if (global.log_send_hostname != NULL) {
1254 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1255 err_code |= ERR_ALERT;
1256 goto out;
1257 }
1258
1259 if (*(args[1]))
1260 name = args[1];
1261 else
1262 name = hostname;
1263
1264 len = strlen(name);
1265
1266 /* We'll add a space after the name to respect the log format */
1267 free(global.log_send_hostname);
1268 global.log_send_hostname = malloc(len + 2);
1269 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1270 }
Kevinm48936af2010-12-22 16:08:21 +00001271 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1272 if (*(args[1]) == 0) {
1273 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 free(global.log_tag);
1278 global.log_tag = strdup(args[1]);
1279 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001280 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1281 if (global.spread_checks != 0) {
1282 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001283 err_code |= ERR_ALERT;
1284 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001285 }
1286 if (*(args[1]) == 0) {
1287 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001290 }
1291 global.spread_checks = atol(args[1]);
1292 if (global.spread_checks < 0 || global.spread_checks > 50) {
1293 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001294 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001297 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1298#ifdef USE_CPU_AFFINITY
1299 int cur_arg, i;
1300 unsigned int proc = 0;
1301 unsigned long cpus = 0;
1302
1303 if (strcmp(args[1], "all") == 0)
1304 proc = 0xFFFFFFFF;
1305 else if (strcmp(args[1], "odd") == 0)
1306 proc = 0x55555555;
1307 else if (strcmp(args[1], "even") == 0)
1308 proc = 0xAAAAAAAA;
1309 else {
1310 proc = atoi(args[1]);
1311 if (proc >= 1 && proc <= 32)
1312 proc = 1 << (proc - 1);
1313 }
1314
1315 if (!proc || !*args[2]) {
1316 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1317 file, linenum, args[0]);
1318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
1320 }
1321
1322 cur_arg = 2;
1323 while (*args[cur_arg]) {
1324 unsigned int low, high;
1325
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001326 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001327 char *dash = strchr(args[cur_arg], '-');
1328
1329 low = high = str2uic(args[cur_arg]);
1330 if (dash)
1331 high = str2uic(dash + 1);
1332
1333 if (high < low) {
1334 unsigned int swap = low;
1335 low = high;
1336 high = swap;
1337 }
1338
1339 if (low < 0 || high >= sizeof(long) * 8) {
1340 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1341 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345
1346 while (low <= high)
1347 cpus |= 1UL << low++;
1348 }
1349 else {
1350 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1351 file, linenum, args[0], args[cur_arg]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 cur_arg++;
1356 }
1357 for (i = 0; i < 32; i++)
1358 if (proc & (1 << i))
1359 global.cpu_map[i] = cpus;
1360#else
1361 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364#endif
1365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001367 struct cfg_kw_list *kwl;
1368 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001369 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001370
1371 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1372 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1373 if (kwl->kw[index].section != CFG_GLOBAL)
1374 continue;
1375 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001376 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001377 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001378 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001380 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001381 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001382 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 err_code |= ERR_WARN;
1384 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001385 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001386 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001387 }
1388 }
1389 }
1390
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001394
Willy Tarreau058e9072009-07-20 09:30:05 +02001395 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001396 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001397 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398}
1399
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001400void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001402 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 defproxy.mode = PR_MODE_TCP;
1404 defproxy.state = PR_STNEW;
1405 defproxy.maxconn = cfg_maxpconn;
1406 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001407
Simon Horman66183002013-02-23 10:16:43 +09001408 defproxy.defsrv.check.inter = DEF_CHKINTR;
1409 defproxy.defsrv.check.fastinter = 0;
1410 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001411 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1412 defproxy.defsrv.agent.fastinter = 0;
1413 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001414 defproxy.defsrv.check.rise = DEF_RISETIME;
1415 defproxy.defsrv.check.fall = DEF_FALLTIME;
1416 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1417 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001418 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001419 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001420 defproxy.defsrv.maxqueue = 0;
1421 defproxy.defsrv.minconn = 0;
1422 defproxy.defsrv.maxconn = 0;
1423 defproxy.defsrv.slowstart = 0;
1424 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1425 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1426 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427}
1428
Willy Tarreauade5ec42010-01-28 19:33:49 +01001429
1430static int create_cond_regex_rule(const char *file, int line,
1431 struct proxy *px, int dir, int action, int flags,
1432 const char *cmd, const char *reg, const char *repl,
1433 const char **cond_start)
1434{
1435 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001436 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001437 const char *err;
1438 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001439 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001440
1441 if (px == &defproxy) {
1442 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto err;
1445 }
1446
1447 if (*reg == 0) {
1448 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1449 err_code |= ERR_ALERT | ERR_FATAL;
1450 goto err;
1451 }
1452
1453 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1454 err_code |= ERR_WARN;
1455
Willy Tarreau5321c422010-01-28 20:35:13 +01001456 if (cond_start &&
1457 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001458 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1459 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1460 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto err;
1463 }
1464 }
1465 else if (cond_start && **cond_start) {
1466 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1467 file, line, cmd, *cond_start);
1468 err_code |= ERR_ALERT | ERR_FATAL;
1469 goto err;
1470 }
1471
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001472 err_code |= warnif_cond_conflicts(cond,
1473 (dir == SMP_OPT_DIR_REQ) ?
1474 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1475 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1476 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001477
Willy Tarreauade5ec42010-01-28 19:33:49 +01001478 preg = calloc(1, sizeof(regex_t));
1479 if (!preg) {
1480 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1481 err_code = ERR_ALERT | ERR_FATAL;
1482 goto err;
1483 }
1484
1485 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1486 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1487 err_code = ERR_ALERT | ERR_FATAL;
1488 goto err;
1489 }
1490
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001491 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001492 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001493 if (repl && err) {
1494 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1495 file, line, cmd, *err);
1496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto err;
1498 }
1499
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001500 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001501 err_code |= ERR_WARN;
1502
Willy Tarreauf4068b62012-05-08 17:37:49 +02001503 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001504 return err_code;
1505 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001506 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001507 free(preg);
1508 return err_code;
1509}
1510
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001513 * Returns the error code, 0 if OK, or any combination of :
1514 * - ERR_ABORT: must abort ASAP
1515 * - ERR_FATAL: we can continue parsing but not start the service
1516 * - ERR_WARN: a warning has been emitted
1517 * - ERR_ALERT: an alert has been emitted
1518 * Only the two first ones can stop processing, the two others are just
1519 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001521int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1522{
1523 static struct peers *curpeers = NULL;
1524 struct peer *newpeer = NULL;
1525 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001526 struct bind_conf *bind_conf;
1527 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001528 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001529 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001530
1531 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001532 if (!*args[1]) {
1533 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001534 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001535 goto out;
1536 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001537
1538 err = invalid_char(args[1]);
1539 if (err) {
1540 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1541 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001542 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001543 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 }
1545
1546 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1547 /*
1548 * If there are two proxies with the same name only following
1549 * combinations are allowed:
1550 */
1551 if (strcmp(curpeers->id, args[1]) == 0) {
1552 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1553 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1554 err_code |= ERR_WARN;
1555 }
1556 }
1557
1558 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
1563
1564 curpeers->next = peers;
1565 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001566 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001567 curpeers->conf.line = linenum;
1568 curpeers->last_change = now.tv_sec;
1569 curpeers->id = strdup(args[1]);
1570 }
1571 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001572 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001573 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001574 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001575
1576 if (!*args[2]) {
1577 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1578 file, linenum, args[0]);
1579 err_code |= ERR_ALERT | ERR_FATAL;
1580 goto out;
1581 }
1582
1583 err = invalid_char(args[1]);
1584 if (err) {
1585 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1586 file, linenum, *err, args[1]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
1591 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1592 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1593 err_code |= ERR_ALERT | ERR_ABORT;
1594 goto out;
1595 }
1596
1597 /* the peers are linked backwards first */
1598 curpeers->count++;
1599 newpeer->next = curpeers->remote;
1600 curpeers->remote = newpeer;
1601 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001602 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001603 newpeer->conf.line = linenum;
1604
1605 newpeer->last_change = now.tv_sec;
1606 newpeer->id = strdup(args[1]);
1607
Willy Tarreau902636f2013-03-10 19:44:48 +01001608 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001609 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001610 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001611 err_code |= ERR_ALERT | ERR_FATAL;
1612 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001613 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001614
1615 proto = protocol_by_family(sk->ss_family);
1616 if (!proto || !proto->connect) {
1617 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1618 file, linenum, args[0], args[1]);
1619 err_code |= ERR_ALERT | ERR_FATAL;
1620 goto out;
1621 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001622
1623 if (port1 != port2) {
1624 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1625 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
1629
Willy Tarreau2aa38802013-02-20 19:20:59 +01001630 if (!port1) {
1631 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1632 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001633 err_code |= ERR_ALERT | ERR_FATAL;
1634 goto out;
1635 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001636
Emeric Brun32da3c42010-09-23 18:39:19 +02001637 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001638 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001639 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001640 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001641
Emeric Brun32da3c42010-09-23 18:39:19 +02001642 if (strcmp(newpeer->id, localpeer) == 0) {
1643 /* Current is local peer, it define a frontend */
1644 newpeer->local = 1;
1645
1646 if (!curpeers->peers_fe) {
1647 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1648 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1649 err_code |= ERR_ALERT | ERR_ABORT;
1650 goto out;
1651 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001652
Willy Tarreau237250c2011-07-29 01:49:03 +02001653 init_new_proxy(curpeers->peers_fe);
1654 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001655
1656 curpeers->peers_fe->last_change = now.tv_sec;
1657 curpeers->peers_fe->id = strdup(args[1]);
1658 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001659 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001660 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1661 curpeers->peers_fe->timeout.connect = 5000;
1662 curpeers->peers_fe->accept = peer_accept;
1663 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001664 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1665 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001666
1667 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1668
Willy Tarreau902636f2013-03-10 19:44:48 +01001669 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1670 if (errmsg && *errmsg) {
1671 indent_msg(&errmsg, 2);
1672 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001673 }
1674 else
1675 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1676 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001677 err_code |= ERR_FATAL;
1678 goto out;
1679 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001680
1681 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1682 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1683 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1684 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1685 l->accept = session_accept;
1686 l->handler = process_session;
1687 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1688 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1689 global.maxsock += l->maxconn;
1690 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001691 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001692 else {
1693 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1694 file, linenum, args[0], args[1],
1695 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1696 err_code |= ERR_FATAL;
1697 goto out;
1698 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001699 }
1700 } /* neither "peer" nor "peers" */
1701 else if (*args[0] != 0) {
1702 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
1705 }
1706
1707out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001708 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001709 return err_code;
1710}
1711
Willy Tarreau3842f002009-06-14 11:39:52 +02001712int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713{
1714 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001715 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001716 int rc;
1717 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001718 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001719 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001720 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001721 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001722 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723
Willy Tarreau977b8e42006-12-29 14:19:17 +01001724 if (!strcmp(args[0], "listen"))
1725 rc = PR_CAP_LISTEN;
1726 else if (!strcmp(args[0], "frontend"))
1727 rc = PR_CAP_FE | PR_CAP_RS;
1728 else if (!strcmp(args[0], "backend"))
1729 rc = PR_CAP_BE | PR_CAP_RS;
1730 else if (!strcmp(args[0], "ruleset"))
1731 rc = PR_CAP_RS;
1732 else
1733 rc = PR_CAP_NONE;
1734
1735 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001736 struct ebpt_node *node;
1737
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738 if (!*args[1]) {
1739 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1740 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1741 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_ABORT;
1743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001745
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001746 err = invalid_char(args[1]);
1747 if (err) {
1748 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1749 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001751 }
1752
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001753 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1754 curproxy = container_of(node, struct proxy, conf.by_name);
1755
1756 if (strcmp(curproxy->id, args[1]) != 0)
1757 break;
1758
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001759 /*
1760 * If there are two proxies with the same name only following
1761 * combinations are allowed:
1762 *
1763 * listen backend frontend ruleset
1764 * listen - - - -
1765 * backend - - OK -
1766 * frontend - OK - -
1767 * ruleset - - - -
1768 */
1769
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001770 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1771 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001772 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1773 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1774 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001775 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001776 }
1777 }
1778
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1780 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001781 err_code |= ERR_ALERT | ERR_ABORT;
1782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001784
Willy Tarreau97cb7802010-01-03 20:23:58 +01001785 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 curproxy->next = proxy;
1787 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001788 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1789 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001790 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001793 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794
1795 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001796 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001797 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001798
Willy Tarreau4348fad2012-09-20 16:48:07 +02001799 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1800
Willy Tarreau902636f2013-03-10 19:44:48 +01001801 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1802 if (errmsg && *errmsg) {
1803 indent_msg(&errmsg, 2);
1804 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001805 }
1806 else
1807 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1808 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_FATAL;
1810 goto out;
1811 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001812
Willy Tarreau4348fad2012-09-20 16:48:07 +02001813 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001814 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 }
1817
1818 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001819 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001820 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001821
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001824 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001825 curproxy->no_options = defproxy.no_options;
1826 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001827 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001828 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001829 curproxy->except_net = defproxy.except_net;
1830 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001831 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001832 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001834 if (defproxy.fwdfor_hdr_len) {
1835 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1836 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1837 }
1838
Willy Tarreaub86db342009-11-30 11:50:16 +01001839 if (defproxy.orgto_hdr_len) {
1840 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1841 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1842 }
1843
Mark Lamourinec2247f02012-01-04 13:02:01 -05001844 if (defproxy.server_id_hdr_len) {
1845 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1846 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1847 }
1848
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 if (curproxy->cap & PR_CAP_FE) {
1850 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001851 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001852 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853
1854 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001855 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1856 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857
1858 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 if (curproxy->cap & PR_CAP_BE) {
1862 curproxy->fullconn = defproxy.fullconn;
1863 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001865 if (defproxy.check_req) {
1866 curproxy->check_req = calloc(1, defproxy.check_len);
1867 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1868 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001869 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001871 if (defproxy.expect_str) {
1872 curproxy->expect_str = strdup(defproxy.expect_str);
1873 if (defproxy.expect_regex) {
1874 /* note: this regex is known to be valid */
1875 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1876 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1877 }
1878 }
1879
Willy Tarreau67402132012-05-31 20:40:20 +02001880 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001881 if (defproxy.cookie_name)
1882 curproxy->cookie_name = strdup(defproxy.cookie_name);
1883 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001884 if (defproxy.cookie_domain)
1885 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001886
Willy Tarreau31936852010-10-06 16:59:56 +02001887 if (defproxy.cookie_maxidle)
1888 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1889
1890 if (defproxy.cookie_maxlife)
1891 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1892
Emeric Brun647caf12009-06-30 17:57:00 +02001893 if (defproxy.rdp_cookie_name)
1894 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1895 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1896
Willy Tarreau01732802007-11-01 22:48:15 +01001897 if (defproxy.url_param_name)
1898 curproxy->url_param_name = strdup(defproxy.url_param_name);
1899 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001900
Benoitaffb4812009-03-25 13:02:10 +01001901 if (defproxy.hh_name)
1902 curproxy->hh_name = strdup(defproxy.hh_name);
1903 curproxy->hh_len = defproxy.hh_len;
1904 curproxy->hh_match_domain = defproxy.hh_match_domain;
1905
Willy Tarreauef9a3602012-12-08 22:29:20 +01001906 if (defproxy.conn_src.iface_name)
1907 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1908 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001909 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001910#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001911 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001912#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001915 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (defproxy.capture_name)
1917 curproxy->capture_name = strdup(defproxy.capture_name);
1918 curproxy->capture_namelen = defproxy.capture_namelen;
1919 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001923 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001924 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001925 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001926 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001927 curproxy->uri_auth = defproxy.uri_auth;
1928 curproxy->mon_net = defproxy.mon_net;
1929 curproxy->mon_mask = defproxy.mon_mask;
1930 if (defproxy.monitor_uri)
1931 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1932 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001933 if (defproxy.defbe.name)
1934 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001935
1936 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001937 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1938 if (curproxy->conf.logformat_string &&
1939 curproxy->conf.logformat_string != default_http_log_format &&
1940 curproxy->conf.logformat_string != default_tcp_log_format &&
1941 curproxy->conf.logformat_string != clf_http_log_format)
1942 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1943
1944 if (defproxy.conf.lfs_file) {
1945 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1946 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1947 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001948 }
1949
1950 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001951 curproxy->timeout.connect = defproxy.timeout.connect;
1952 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001953 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001954 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001955 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001956 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001957 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001958 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001959 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001960 }
1961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001963
1964 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001965 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001966 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001967 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001968 LIST_INIT(&node->list);
1969 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1970 }
1971
Willy Tarreau62a61232013-04-12 18:13:46 +02001972 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1973 if (curproxy->conf.uniqueid_format_string)
1974 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1975
1976 if (defproxy.conf.uif_file) {
1977 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1978 curproxy->conf.uif_line = defproxy.conf.uif_line;
1979 }
William Lallemanda73203e2012-03-12 12:48:57 +01001980
1981 /* copy default header unique id */
1982 if (defproxy.header_unique_id)
1983 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1984
William Lallemand82fe75c2012-10-23 10:25:10 +02001985 /* default compression options */
1986 if (defproxy.comp != NULL) {
1987 curproxy->comp = calloc(1, sizeof(struct comp));
1988 curproxy->comp->algos = defproxy.comp->algos;
1989 curproxy->comp->types = defproxy.comp->types;
1990 }
1991
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001993 curproxy->conf.used_listener_id = EB_ROOT;
1994 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001995
Willy Tarreau93893792009-07-23 13:19:11 +02001996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 }
1998 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1999 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002000 /* FIXME-20070101: we should do this too at the end of the
2001 * config parsing to free all default values.
2002 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002003 free(defproxy.check_req);
2004 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002005 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002006 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002007 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002008 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002009 free(defproxy.capture_name);
2010 free(defproxy.monitor_uri);
2011 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002012 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002013 free(defproxy.fwdfor_hdr_name);
2014 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002015 free(defproxy.orgto_hdr_name);
2016 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002017 free(defproxy.server_id_hdr_name);
2018 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002019 free(defproxy.expect_str);
2020 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002021
Willy Tarreau62a61232013-04-12 18:13:46 +02002022 if (defproxy.conf.logformat_string != default_http_log_format &&
2023 defproxy.conf.logformat_string != default_tcp_log_format &&
2024 defproxy.conf.logformat_string != clf_http_log_format)
2025 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002026
Willy Tarreau62a61232013-04-12 18:13:46 +02002027 free(defproxy.conf.uniqueid_format_string);
2028 free(defproxy.conf.lfs_file);
2029 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002030
Willy Tarreaua534fea2008-08-03 12:19:50 +02002031 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002032 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002033
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 /* we cannot free uri_auth because it might already be used */
2035 init_default_instance();
2036 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002037 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2038 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
2042 else if (curproxy == NULL) {
2043 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002047
2048 /* update the current file and line being parsed */
2049 curproxy->conf.args.file = curproxy->conf.file;
2050 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002051
2052 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002053 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2054 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2055 if (err_code & ERR_FATAL)
2056 goto out;
2057 }
2058 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002059 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002060 int cur_arg;
2061
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 if (curproxy == &defproxy) {
2063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002067 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069
Willy Tarreau24709282013-03-10 21:32:12 +01002070 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002071 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002076
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002077 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002078
2079 /* use default settings for unix sockets */
2080 bind_conf->ux.uid = global.unix_bind.ux.uid;
2081 bind_conf->ux.gid = global.unix_bind.ux.gid;
2082 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002083
2084 /* NOTE: the following line might create several listeners if there
2085 * are comma-separated IPs or port ranges. So all further processing
2086 * will have to be applied to all listeners created after last_listen.
2087 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002088 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2089 if (errmsg && *errmsg) {
2090 indent_msg(&errmsg, 2);
2091 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002092 }
2093 else
2094 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2095 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
2098 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002099
Willy Tarreau4348fad2012-09-20 16:48:07 +02002100 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2101 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002102 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002103 }
2104
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002105 cur_arg = 2;
2106 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002107 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002108 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002109 char *err;
2110
Willy Tarreau26982662012-09-12 23:17:10 +02002111 kw = bind_find_kw(args[cur_arg]);
2112 if (kw) {
2113 char *err = NULL;
2114 int code;
2115
2116 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002117 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2118 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002119 cur_arg += 1 + kw->skip ;
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
2123
Willy Tarreau4348fad2012-09-20 16:48:07 +02002124 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002125 err_code |= code;
2126
2127 if (code) {
2128 if (err && *err) {
2129 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002130 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002131 }
2132 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002133 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2134 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002135 if (code & ERR_FATAL) {
2136 free(err);
2137 cur_arg += 1 + kw->skip;
2138 goto out;
2139 }
2140 }
2141 free(err);
2142 cur_arg += 1 + kw->skip;
2143 continue;
2144 }
2145
Willy Tarreau8638f482012-09-18 18:01:17 +02002146 err = NULL;
2147 if (!bind_dumped) {
2148 bind_dump_kws(&err);
2149 indent_msg(&err, 4);
2150 bind_dumped = 1;
2151 }
2152
2153 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2154 file, linenum, args[0], args[1], args[cur_arg],
2155 err ? " Registered keywords :" : "", err ? err : "");
2156 free(err);
2157
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002160 }
Willy Tarreau93893792009-07-23 13:19:11 +02002161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 }
2163 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002164 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2166 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002169 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002170 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002171 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002172
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 /* flush useless bits */
2174 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002177 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002178 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002179 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002180
Willy Tarreau1c47f852006-07-09 08:22:27 +02002181 if (!*args[1]) {
2182 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2183 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002186 }
2187
Willy Tarreaua534fea2008-08-03 12:19:50 +02002188 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002189 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002190 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002191 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002192 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2193
Willy Tarreau93893792009-07-23 13:19:11 +02002194 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2197 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2198 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2199 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2200 else {
2201 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 }
2205 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002206 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002207 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002208
2209 if (curproxy == &defproxy) {
2210 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2211 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002214 }
2215
2216 if (!*args[1]) {
2217 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2218 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002221 }
2222
2223 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002224 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002225
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002226 if (curproxy->uuid <= 0) {
2227 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002228 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002231 }
2232
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002233 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2234 if (node) {
2235 struct proxy *target = container_of(node, struct proxy, conf.id);
2236 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2237 file, linenum, proxy_type_str(curproxy), curproxy->id,
2238 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002243 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002244 else if (!strcmp(args[0], "description")) {
2245 int i, len=0;
2246 char *d;
2247
Cyril Bonté99ed3272010-01-24 23:29:44 +01002248 if (curproxy == &defproxy) {
2249 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2250 file, linenum, args[0]);
2251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002255 if (!*args[1]) {
2256 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2257 file, linenum, args[0]);
2258 return -1;
2259 }
2260
Willy Tarreau348acfe2014-04-14 15:00:39 +02002261 for (i = 1; *args[i]; i++)
2262 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002263
2264 d = (char *)calloc(1, len);
2265 curproxy->desc = d;
2266
Willy Tarreau348acfe2014-04-14 15:00:39 +02002267 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2268 for (i = 2; *args[i]; i++)
2269 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002270
2271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2273 curproxy->state = PR_STSTOPPED;
2274 }
2275 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2276 curproxy->state = PR_STNEW;
2277 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002278 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2279 int cur_arg = 1;
2280 unsigned int set = 0;
2281
2282 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002283 unsigned int low, high;
2284
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002285 if (strcmp(args[cur_arg], "all") == 0) {
2286 set = 0;
2287 break;
2288 }
2289 else if (strcmp(args[cur_arg], "odd") == 0) {
2290 set |= 0x55555555;
2291 }
2292 else if (strcmp(args[cur_arg], "even") == 0) {
2293 set |= 0xAAAAAAAA;
2294 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002295 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002296 char *dash = strchr(args[cur_arg], '-');
2297
2298 low = high = str2uic(args[cur_arg]);
2299 if (dash)
2300 high = str2uic(dash + 1);
2301
2302 if (high < low) {
2303 unsigned int swap = low;
2304 low = high;
2305 high = swap;
2306 }
2307
2308 if (low < 1 || high > 32) {
2309 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002313 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002314
2315 if (high > global.nbproc) {
2316 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2317 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002319 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002320 while (low <= high)
2321 set |= 1 << (low++ - 1);
2322 }
2323 else {
2324 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2325 file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002328 }
2329 cur_arg++;
2330 }
2331 curproxy->bind_proc = set;
2332 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002333 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002334 if (curproxy == &defproxy) {
2335 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002338 }
2339
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002340 err = invalid_char(args[1]);
2341 if (err) {
2342 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2343 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002345 }
2346
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002347 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002348 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2349 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002352 }
2353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2355 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 if (*(args[1]) == 0) {
2361 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2362 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002366
Willy Tarreau67402132012-05-31 20:40:20 +02002367 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002368 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002369 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002370 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 curproxy->cookie_name = strdup(args[1]);
2372 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002373
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 cur_arg = 2;
2375 while (*(args[cur_arg])) {
2376 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002377 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002380 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
2382 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002383 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002386 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
2388 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002389 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002391 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002392 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002395 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002397 else if (!strcmp(args[cur_arg], "httponly")) {
2398 curproxy->ck_opts |= PR_CK_HTTPONLY;
2399 }
2400 else if (!strcmp(args[cur_arg], "secure")) {
2401 curproxy->ck_opts |= PR_CK_SECURE;
2402 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002403 else if (!strcmp(args[cur_arg], "domain")) {
2404 if (!*args[cur_arg + 1]) {
2405 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2406 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002409 }
2410
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002411 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002412 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002413 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2414 " dots nor does not start with a dot."
2415 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002416 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002417 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002418 }
2419
2420 err = invalid_domainchar(args[cur_arg + 1]);
2421 if (err) {
2422 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2423 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002426 }
2427
Willy Tarreau68a897b2009-12-03 23:28:34 +01002428 if (!curproxy->cookie_domain) {
2429 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2430 } else {
2431 /* one domain was already specified, add another one by
2432 * building the string which will be returned along with
2433 * the cookie.
2434 */
2435 char *new_ptr;
2436 int new_len = strlen(curproxy->cookie_domain) +
2437 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2438 new_ptr = malloc(new_len);
2439 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2440 free(curproxy->cookie_domain);
2441 curproxy->cookie_domain = new_ptr;
2442 }
Willy Tarreau31936852010-10-06 16:59:56 +02002443 cur_arg++;
2444 }
2445 else if (!strcmp(args[cur_arg], "maxidle")) {
2446 unsigned int maxidle;
2447 const char *res;
2448
2449 if (!*args[cur_arg + 1]) {
2450 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2451 file, linenum, args[cur_arg]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2457 if (res) {
2458 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2459 file, linenum, *res, args[cur_arg]);
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
2462 }
2463 curproxy->cookie_maxidle = maxidle;
2464 cur_arg++;
2465 }
2466 else if (!strcmp(args[cur_arg], "maxlife")) {
2467 unsigned int maxlife;
2468 const char *res;
2469
2470 if (!*args[cur_arg + 1]) {
2471 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2472 file, linenum, args[cur_arg]);
2473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
2475 }
2476
2477 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2478 if (res) {
2479 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2480 file, linenum, *res, args[cur_arg]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002485 cur_arg++;
2486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002488 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 }
2493 cur_arg++;
2494 }
Willy Tarreau67402132012-05-31 20:40:20 +02002495 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2497 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 }
2500
Willy Tarreau67402132012-05-31 20:40:20 +02002501 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2503 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002506
Willy Tarreau67402132012-05-31 20:40:20 +02002507 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002508 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2509 file, linenum);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002513 else if (!strcmp(args[0], "persist")) { /* persist */
2514 if (*(args[1]) == 0) {
2515 Alert("parsing [%s:%d] : missing persist method.\n",
2516 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002519 }
2520
2521 if (!strncmp(args[1], "rdp-cookie", 10)) {
2522 curproxy->options2 |= PR_O2_RDPC_PRST;
2523
Emeric Brunb982a3d2010-01-04 15:45:53 +01002524 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002525 const char *beg, *end;
2526
2527 beg = args[1] + 11;
2528 end = strchr(beg, ')');
2529
2530 if (!end || end == beg) {
2531 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2532 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002535 }
2536
2537 free(curproxy->rdp_cookie_name);
2538 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2539 curproxy->rdp_cookie_len = end-beg;
2540 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002541 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002542 free(curproxy->rdp_cookie_name);
2543 curproxy->rdp_cookie_name = strdup("msts");
2544 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2545 }
2546 else { /* syntax */
2547 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2548 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002551 }
2552 }
2553 else {
2554 Alert("parsing [%s:%d] : unknown persist method.\n",
2555 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002558 }
2559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002561 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002563 if (curproxy == &defproxy) {
2564 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
2567 }
2568
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002573 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
2578 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002579 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 curproxy->appsession_name = strdup(args[1]);
2581 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2582 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002583 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2584 if (err) {
2585 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2586 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002589 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002590 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002591
Willy Tarreau51041c72007-09-09 21:56:53 +02002592 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2593 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_ABORT;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002597
2598 cur_arg = 6;
2599 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002600 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2601 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002602 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002603 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002604 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002605 } else if (!strcmp(args[cur_arg], "prefix")) {
2606 curproxy->options2 |= PR_O2_AS_PFX;
2607 } else if (!strcmp(args[cur_arg], "mode")) {
2608 if (!*args[cur_arg + 1]) {
2609 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2610 file, linenum, args[0], args[cur_arg]);
2611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
2613 }
2614
2615 cur_arg++;
2616 if (!strcmp(args[cur_arg], "query-string")) {
2617 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2618 curproxy->options2 |= PR_O2_AS_M_QS;
2619 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2620 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2621 curproxy->options2 |= PR_O2_AS_M_PP;
2622 } else {
2623 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002628 cur_arg++;
2629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 } /* Url App Session */
2631 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002632 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002634
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002636 if (curproxy == &defproxy) {
2637 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
2640 }
2641
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 if (*(args[4]) == 0) {
2643 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002648 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 curproxy->capture_name = strdup(args[2]);
2650 curproxy->capture_namelen = strlen(curproxy->capture_name);
2651 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 curproxy->to_log |= LW_COOKIE;
2653 }
2654 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2655 struct cap_hdr *hdr;
2656
2657 if (curproxy == &defproxy) {
2658 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 }
2662
2663 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2664 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2665 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 }
2669
2670 hdr = calloc(sizeof(struct cap_hdr), 1);
2671 hdr->next = curproxy->req_cap;
2672 hdr->name = strdup(args[3]);
2673 hdr->namelen = strlen(args[3]);
2674 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002675 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 hdr->index = curproxy->nb_req_cap++;
2677 curproxy->req_cap = hdr;
2678 curproxy->to_log |= LW_REQHDR;
2679 }
2680 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2681 struct cap_hdr *hdr;
2682
2683 if (curproxy == &defproxy) {
2684 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 }
2688
2689 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2690 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2691 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 }
2695 hdr = calloc(sizeof(struct cap_hdr), 1);
2696 hdr->next = curproxy->rsp_cap;
2697 hdr->name = strdup(args[3]);
2698 hdr->namelen = strlen(args[3]);
2699 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002700 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 hdr->index = curproxy->nb_rsp_cap++;
2702 curproxy->rsp_cap = hdr;
2703 curproxy->to_log |= LW_RSPHDR;
2704 }
2705 else {
2706 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 }
2711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002713 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 if (*(args[1]) == 0) {
2717 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 }
2722 curproxy->conn_retries = atol(args[1]);
2723 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002724 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002725 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002726
2727 if (curproxy == &defproxy) {
2728 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
2731 }
2732
Willy Tarreau20b0de52012-12-24 15:45:22 +01002733 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2734 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2735 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2736 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002737 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002738 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2739 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002740 file, linenum, args[0]);
2741 err_code |= ERR_WARN;
2742 }
2743
Willy Tarreauff011f22011-01-06 17:51:27 +01002744 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002745
Willy Tarreauff011f22011-01-06 17:51:27 +01002746 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002747 err_code |= ERR_ALERT | ERR_ABORT;
2748 goto out;
2749 }
2750
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002751 err_code |= warnif_cond_conflicts(rule->cond,
2752 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2753 file, linenum);
2754
Willy Tarreauff011f22011-01-06 17:51:27 +01002755 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002756 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002757 else if (!strcmp(args[0], "http-response")) { /* response access control */
2758 struct http_res_rule *rule;
2759
2760 if (curproxy == &defproxy) {
2761 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
2766 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2767 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2768 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2769 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2770 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2771 file, linenum, args[0]);
2772 err_code |= ERR_WARN;
2773 }
2774
2775 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2776
2777 if (!rule) {
2778 err_code |= ERR_ALERT | ERR_ABORT;
2779 goto out;
2780 }
2781
2782 err_code |= warnif_cond_conflicts(rule->cond,
2783 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2784 file, linenum);
2785
2786 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2787 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002788 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2789 /* set the header name and length into the proxy structure */
2790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2791 err_code |= ERR_WARN;
2792
2793 if (!*args[1]) {
2794 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2795 file, linenum, args[0]);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
2799
2800 /* set the desired header name */
2801 free(curproxy->server_id_hdr_name);
2802 curproxy->server_id_hdr_name = strdup(args[1]);
2803 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2804 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002805 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002806 if (curproxy == &defproxy) {
2807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002810 }
2811
Willy Tarreauef6494c2010-01-28 17:12:36 +01002812 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002813 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2814 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002817 }
2818
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002819 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2820 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2821 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002824 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002825
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002826 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002827 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002828 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002829 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002830 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002831
Cyril Bonté99ed3272010-01-24 23:29:44 +01002832 if (curproxy == &defproxy) {
2833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002838 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002839 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2840 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002843 }
2844
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002845 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002846 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002847 err_code |= warnif_cond_conflicts(rule->cond,
2848 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2849 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002850 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002851 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002852 struct switching_rule *rule;
2853
Willy Tarreaub099aca2008-10-12 17:26:37 +02002854 if (curproxy == &defproxy) {
2855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002858 }
2859
Willy Tarreau55ea7572007-06-17 19:56:27 +02002860 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002862
2863 if (*(args[1]) == 0) {
2864 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002867 }
2868
Willy Tarreauf51658d2014-04-23 01:21:56 +02002869 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2870 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2871 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2872 file, linenum, errmsg);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002876
Willy Tarreauf51658d2014-04-23 01:21:56 +02002877 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002878 }
2879
2880 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2881 rule->cond = cond;
2882 rule->be.name = strdup(args[1]);
2883 LIST_INIT(&rule->list);
2884 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2885 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002886 else if (strcmp(args[0], "use-server") == 0) {
2887 struct server_rule *rule;
2888
2889 if (curproxy == &defproxy) {
2890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
2893 }
2894
2895 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2896 err_code |= ERR_WARN;
2897
2898 if (*(args[1]) == 0) {
2899 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902 }
2903
2904 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2905 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2906 file, linenum, args[0]);
2907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
2909 }
2910
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002911 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2912 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2913 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
2916 }
2917
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002918 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002919
2920 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2921 rule->cond = cond;
2922 rule->srv.name = strdup(args[1]);
2923 LIST_INIT(&rule->list);
2924 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2925 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2926 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002927 else if ((!strcmp(args[0], "force-persist")) ||
2928 (!strcmp(args[0], "ignore-persist"))) {
2929 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002930
2931 if (curproxy == &defproxy) {
2932 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936
2937 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2938 err_code |= ERR_WARN;
2939
Willy Tarreauef6494c2010-01-28 17:12:36 +01002940 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002941 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2942 file, linenum, args[0]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002947 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2948 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2949 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002954 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2955 * where force-persist is applied.
2956 */
2957 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002958
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002959 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002960 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002961 if (!strcmp(args[0], "force-persist")) {
2962 rule->type = PERSIST_TYPE_FORCE;
2963 } else {
2964 rule->type = PERSIST_TYPE_IGNORE;
2965 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002966 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002967 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002968 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002969 else if (!strcmp(args[0], "stick-table")) {
2970 int myidx = 1;
2971
Emeric Brun32da3c42010-09-23 18:39:19 +02002972 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002973 curproxy->table.type = (unsigned int)-1;
2974 while (*args[myidx]) {
2975 const char *err;
2976
2977 if (strcmp(args[myidx], "size") == 0) {
2978 myidx++;
2979 if (!*(args[myidx])) {
2980 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2981 file, linenum, args[myidx-1]);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
2985 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2986 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2987 file, linenum, *err, args[myidx-1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002991 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002992 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002993 else if (strcmp(args[myidx], "peers") == 0) {
2994 myidx++;
Godbach50523162013-12-11 19:48:57 +08002995 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08002996 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2997 file, linenum, args[myidx-1]);
2998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Godbach50523162013-12-11 19:48:57 +08003000 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003001 curproxy->table.peers.name = strdup(args[myidx++]);
3002 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003003 else if (strcmp(args[myidx], "expire") == 0) {
3004 myidx++;
3005 if (!*(args[myidx])) {
3006 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3007 file, linenum, args[myidx-1]);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
3011 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3012 if (err) {
3013 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3014 file, linenum, *err, args[myidx-1]);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
3018 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003019 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 }
3021 else if (strcmp(args[myidx], "nopurge") == 0) {
3022 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003023 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 }
3025 else if (strcmp(args[myidx], "type") == 0) {
3026 myidx++;
3027 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3028 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3029 file, linenum, args[myidx]);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003033 /* myidx already points to next arg */
3034 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003035 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003036 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003037 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003038
3039 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003040 nw = args[myidx];
3041 while (*nw) {
3042 /* the "store" keyword supports a comma-separated list */
3043 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003044 sa = NULL; /* store arg */
3045 while (*nw && *nw != ',') {
3046 if (*nw == '(') {
3047 *nw = 0;
3048 sa = ++nw;
3049 while (*nw != ')') {
3050 if (!*nw) {
3051 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3052 file, linenum, args[0], cw);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056 nw++;
3057 }
3058 *nw = '\0';
3059 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003060 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003061 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003062 if (*nw)
3063 *nw++ = '\0';
3064 type = stktable_get_data_type(cw);
3065 if (type < 0) {
3066 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3067 file, linenum, args[0], cw);
3068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
3070 }
Willy Tarreauac782882010-06-20 10:41:54 +02003071
3072 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3073 switch (err) {
3074 case PE_NONE: break;
3075 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003076 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3077 file, linenum, args[0], cw);
3078 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003079 break;
3080
3081 case PE_ARG_MISSING:
3082 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3083 file, linenum, args[0], cw);
3084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
3086
3087 case PE_ARG_NOT_USED:
3088 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3089 file, linenum, args[0], cw);
3090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
3092
3093 default:
3094 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3095 file, linenum, args[0], cw);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003098 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003099 }
3100 myidx++;
3101 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003102 else {
3103 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3104 file, linenum, args[myidx]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003107 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003108 }
3109
3110 if (!curproxy->table.size) {
3111 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3112 file, linenum);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116
3117 if (curproxy->table.type == (unsigned int)-1) {
3118 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3119 file, linenum);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123 }
3124 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003125 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003126 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003127 int myidx = 0;
3128 const char *name = NULL;
3129 int flags;
3130
3131 if (curproxy == &defproxy) {
3132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
3135 }
3136
3137 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3138 err_code |= ERR_WARN;
3139 goto out;
3140 }
3141
3142 myidx++;
3143 if ((strcmp(args[myidx], "store") == 0) ||
3144 (strcmp(args[myidx], "store-request") == 0)) {
3145 myidx++;
3146 flags = STK_IS_STORE;
3147 }
3148 else if (strcmp(args[myidx], "store-response") == 0) {
3149 myidx++;
3150 flags = STK_IS_STORE | STK_ON_RSP;
3151 }
3152 else if (strcmp(args[myidx], "match") == 0) {
3153 myidx++;
3154 flags = STK_IS_MATCH;
3155 }
3156 else if (strcmp(args[myidx], "on") == 0) {
3157 myidx++;
3158 flags = STK_IS_MATCH | STK_IS_STORE;
3159 }
3160 else {
3161 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165
3166 if (*(args[myidx]) == 0) {
3167 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003172 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003173 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003174 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003175 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
3178 }
3179
3180 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003181 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3182 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3183 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003184 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003185 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003186 goto out;
3187 }
3188 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003189 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3190 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3191 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003192 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003193 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003194 goto out;
3195 }
3196 }
3197
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003198 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003199 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003200
Emeric Brunb982a3d2010-01-04 15:45:53 +01003201 if (strcmp(args[myidx], "table") == 0) {
3202 myidx++;
3203 name = args[myidx++];
3204 }
3205
Willy Tarreauef6494c2010-01-28 17:12:36 +01003206 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003207 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3208 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3209 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003210 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003211 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003212 goto out;
3213 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003214 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003215 else if (*(args[myidx])) {
3216 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3217 file, linenum, args[0], args[myidx]);
3218 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003219 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003220 goto out;
3221 }
Emeric Brun97679e72010-09-23 17:56:44 +02003222 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003223 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003224 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003225 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003226
Emeric Brunb982a3d2010-01-04 15:45:53 +01003227 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3228 rule->cond = cond;
3229 rule->expr = expr;
3230 rule->flags = flags;
3231 rule->table.name = name ? strdup(name) : NULL;
3232 LIST_INIT(&rule->list);
3233 if (flags & STK_ON_RSP)
3234 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3235 else
3236 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003239 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003241
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3243 curproxy->uri_auth = NULL; /* we must detach from the default config */
3244
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003245 if (!*args[1]) {
3246 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003247 } else if (!strcmp(args[1], "admin")) {
3248 struct stats_admin_rule *rule;
3249
3250 if (curproxy == &defproxy) {
3251 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
3254 }
3255
3256 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3257 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3258 err_code |= ERR_ALERT | ERR_ABORT;
3259 goto out;
3260 }
3261
3262 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3263 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3264 file, linenum, args[0], args[1]);
3265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
3267 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003268 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3269 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3270 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003271 err_code |= ERR_ALERT | ERR_FATAL;
3272 goto out;
3273 }
3274
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003275 err_code |= warnif_cond_conflicts(cond,
3276 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3277 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003278
3279 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3280 rule->cond = cond;
3281 LIST_INIT(&rule->list);
3282 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 } else if (!strcmp(args[1], "uri")) {
3284 if (*(args[2]) == 0) {
3285 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_ABORT;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293 } else if (!strcmp(args[1], "realm")) {
3294 if (*(args[2]) == 0) {
3295 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3299 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_ABORT;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003303 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003304 unsigned interval;
3305
3306 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3307 if (err) {
3308 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3309 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003312 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_ABORT;
3315 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003316 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003317 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003318 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003319
3320 if (curproxy == &defproxy) {
3321 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
3324 }
3325
3326 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3327 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3328 err_code |= ERR_ALERT | ERR_ABORT;
3329 goto out;
3330 }
3331
Willy Tarreauff011f22011-01-06 17:51:27 +01003332 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3333 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003334 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3335 file, linenum, args[0]);
3336 err_code |= ERR_WARN;
3337 }
3338
Willy Tarreauff011f22011-01-06 17:51:27 +01003339 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003340
Willy Tarreauff011f22011-01-06 17:51:27 +01003341 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003342 err_code |= ERR_ALERT | ERR_ABORT;
3343 goto out;
3344 }
3345
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003346 err_code |= warnif_cond_conflicts(rule->cond,
3347 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3348 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003349 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003350
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 } else if (!strcmp(args[1], "auth")) {
3352 if (*(args[2]) == 0) {
3353 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_ABORT;
3359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
3361 } else if (!strcmp(args[1], "scope")) {
3362 if (*(args[2]) == 0) {
3363 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3367 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_ABORT;
3369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 }
3371 } else if (!strcmp(args[1], "enable")) {
3372 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3373 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003374 err_code |= ERR_ALERT | ERR_ABORT;
3375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003377 } else if (!strcmp(args[1], "hide-version")) {
3378 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_ABORT;
3381 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003382 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003383 } else if (!strcmp(args[1], "show-legends")) {
3384 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3385 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3386 err_code |= ERR_ALERT | ERR_ABORT;
3387 goto out;
3388 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003389 } else if (!strcmp(args[1], "show-node")) {
3390
3391 if (*args[2]) {
3392 int i;
3393 char c;
3394
3395 for (i=0; args[2][i]; i++) {
3396 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003397 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3398 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003399 break;
3400 }
3401
3402 if (!i || args[2][i]) {
3403 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3404 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3405 file, linenum, args[0], args[1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409 }
3410
3411 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3412 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3413 err_code |= ERR_ALERT | ERR_ABORT;
3414 goto out;
3415 }
3416 } else if (!strcmp(args[1], "show-desc")) {
3417 char *desc = NULL;
3418
3419 if (*args[2]) {
3420 int i, len=0;
3421 char *d;
3422
Willy Tarreau348acfe2014-04-14 15:00:39 +02003423 for (i = 2; *args[i]; i++)
3424 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003425
3426 desc = d = (char *)calloc(1, len);
3427
Willy Tarreau348acfe2014-04-14 15:00:39 +02003428 d += snprintf(d, desc + len - d, "%s", args[2]);
3429 for (i = 3; *args[i]; i++)
3430 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003431 }
3432
3433 if (!*args[2] && !global.desc)
3434 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3435 file, linenum, args[1]);
3436 else {
3437 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3438 free(desc);
3439 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3440 err_code |= ERR_ALERT | ERR_ABORT;
3441 goto out;
3442 }
3443 free(desc);
3444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003446stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003447 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 +01003448 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 }
3452 }
3453 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003454 int optnum;
3455
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003456 if (*(args[1]) == '\0') {
3457 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003462
3463 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3464 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003465 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3466 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3467 file, linenum, cfg_opts[optnum].name);
3468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
3470 }
Willy Tarreau93893792009-07-23 13:19:11 +02003471 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3472 err_code |= ERR_WARN;
3473 goto out;
3474 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003475
Willy Tarreau3842f002009-06-14 11:39:52 +02003476 curproxy->no_options &= ~cfg_opts[optnum].val;
3477 curproxy->options &= ~cfg_opts[optnum].val;
3478
3479 switch (kwm) {
3480 case KWM_STD:
3481 curproxy->options |= cfg_opts[optnum].val;
3482 break;
3483 case KWM_NO:
3484 curproxy->no_options |= cfg_opts[optnum].val;
3485 break;
3486 case KWM_DEF: /* already cleared */
3487 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003488 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003489
Willy Tarreau93893792009-07-23 13:19:11 +02003490 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003491 }
3492 }
3493
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003494 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3495 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003496 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3497 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3498 file, linenum, cfg_opts2[optnum].name);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
Willy Tarreau93893792009-07-23 13:19:11 +02003502 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3503 err_code |= ERR_WARN;
3504 goto out;
3505 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003506
Willy Tarreau3842f002009-06-14 11:39:52 +02003507 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3508 curproxy->options2 &= ~cfg_opts2[optnum].val;
3509
3510 switch (kwm) {
3511 case KWM_STD:
3512 curproxy->options2 |= cfg_opts2[optnum].val;
3513 break;
3514 case KWM_NO:
3515 curproxy->no_options2 |= cfg_opts2[optnum].val;
3516 break;
3517 case KWM_DEF: /* already cleared */
3518 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003519 }
Willy Tarreau93893792009-07-23 13:19:11 +02003520 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003521 }
3522 }
3523
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003524 /* HTTP options override each other. They can be cancelled using
3525 * "no option xxx" which only switches to default mode if the mode
3526 * was this one (useful for cancelling options set in defaults
3527 * sections).
3528 */
3529 if (strcmp(args[1], "httpclose") == 0) {
3530 if (kwm == KWM_STD) {
3531 curproxy->options &= ~PR_O_HTTP_MODE;
3532 curproxy->options |= PR_O_HTTP_PCL;
3533 goto out;
3534 }
3535 else if (kwm == KWM_NO) {
3536 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3537 curproxy->options &= ~PR_O_HTTP_MODE;
3538 goto out;
3539 }
3540 }
3541 else if (strcmp(args[1], "forceclose") == 0) {
3542 if (kwm == KWM_STD) {
3543 curproxy->options &= ~PR_O_HTTP_MODE;
3544 curproxy->options |= PR_O_HTTP_FCL;
3545 goto out;
3546 }
3547 else if (kwm == KWM_NO) {
3548 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3549 curproxy->options &= ~PR_O_HTTP_MODE;
3550 goto out;
3551 }
3552 }
3553 else if (strcmp(args[1], "http-server-close") == 0) {
3554 if (kwm == KWM_STD) {
3555 curproxy->options &= ~PR_O_HTTP_MODE;
3556 curproxy->options |= PR_O_HTTP_SCL;
3557 goto out;
3558 }
3559 else if (kwm == KWM_NO) {
3560 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3561 curproxy->options &= ~PR_O_HTTP_MODE;
3562 goto out;
3563 }
3564 }
3565 else if (strcmp(args[1], "http-keep-alive") == 0) {
3566 if (kwm == KWM_STD) {
3567 curproxy->options &= ~PR_O_HTTP_MODE;
3568 curproxy->options |= PR_O_HTTP_KAL;
3569 goto out;
3570 }
3571 else if (kwm == KWM_NO) {
3572 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3573 curproxy->options &= ~PR_O_HTTP_MODE;
3574 goto out;
3575 }
3576 }
3577 else if (strcmp(args[1], "http-tunnel") == 0) {
3578 if (kwm == KWM_STD) {
3579 curproxy->options &= ~PR_O_HTTP_MODE;
3580 curproxy->options |= PR_O_HTTP_TUN;
3581 goto out;
3582 }
3583 else if (kwm == KWM_NO) {
3584 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3585 curproxy->options &= ~PR_O_HTTP_MODE;
3586 goto out;
3587 }
3588 }
3589
Willy Tarreau3842f002009-06-14 11:39:52 +02003590 if (kwm != KWM_STD) {
3591 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003592 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003595 }
3596
Emeric Brun3a058f32009-06-30 18:26:00 +02003597 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003598 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003600 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003601 if (*(args[2]) != '\0') {
3602 if (!strcmp(args[2], "clf")) {
3603 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003604 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003605 } else {
3606 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003609 }
3610 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003611 if (curproxy->conf.logformat_string != default_http_log_format &&
3612 curproxy->conf.logformat_string != default_tcp_log_format &&
3613 curproxy->conf.logformat_string != clf_http_log_format)
3614 free(curproxy->conf.logformat_string);
3615 curproxy->conf.logformat_string = logformat;
3616
3617 free(curproxy->conf.lfs_file);
3618 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3619 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003620 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003621 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003623 if (curproxy->conf.logformat_string != default_http_log_format &&
3624 curproxy->conf.logformat_string != default_tcp_log_format &&
3625 curproxy->conf.logformat_string != clf_http_log_format)
3626 free(curproxy->conf.logformat_string);
3627 curproxy->conf.logformat_string = default_tcp_log_format;
3628
3629 free(curproxy->conf.lfs_file);
3630 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3631 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 else if (!strcmp(args[1], "tcpka")) {
3634 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003635 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003637
3638 if (curproxy->cap & PR_CAP_FE)
3639 curproxy->options |= PR_O_TCP_CLI_KA;
3640 if (curproxy->cap & PR_CAP_BE)
3641 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
3643 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003644 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_WARN;
3646
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003648 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003649 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003650 curproxy->options2 &= ~PR_O2_CHK_ANY;
3651 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 if (!*args[2]) { /* no argument */
3653 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3654 curproxy->check_len = strlen(DEF_CHECK_REQ);
3655 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003656 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 curproxy->check_req = (char *)malloc(reqlen);
3658 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003659 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003661 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 if (*args[4])
3663 reqlen += strlen(args[4]);
3664 else
3665 reqlen += strlen("HTTP/1.0");
3666
3667 curproxy->check_req = (char *)malloc(reqlen);
3668 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003669 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003671 }
3672 else if (!strcmp(args[1], "ssl-hello-chk")) {
3673 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003674 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003676
Willy Tarreaua534fea2008-08-03 12:19:50 +02003677 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003678 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003679 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003680 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003681 }
Willy Tarreau23677902007-05-08 23:50:35 +02003682 else if (!strcmp(args[1], "smtpchk")) {
3683 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003684 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003685 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003686 curproxy->options2 &= ~PR_O2_CHK_ANY;
3687 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003688
3689 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3690 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3691 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3692 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3693 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3694 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3695 curproxy->check_req = (char *)malloc(reqlen);
3696 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3697 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3698 } else {
3699 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3700 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3701 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3702 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3703 }
3704 }
3705 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003706 else if (!strcmp(args[1], "pgsql-check")) {
3707 /* use PostgreSQL request to check servers' health */
3708 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3709 err_code |= ERR_WARN;
3710
3711 free(curproxy->check_req);
3712 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003713 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003714 curproxy->options2 |= PR_O2_PGSQL_CHK;
3715
3716 if (*(args[2])) {
3717 int cur_arg = 2;
3718
3719 while (*(args[cur_arg])) {
3720 if (strcmp(args[cur_arg], "user") == 0) {
3721 char * packet;
3722 uint32_t packet_len;
3723 uint32_t pv;
3724
3725 /* suboption header - needs additional argument for it */
3726 if (*(args[cur_arg+1]) == 0) {
3727 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3728 file, linenum, args[0], args[1], args[cur_arg]);
3729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
3731 }
3732
3733 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3734 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3735 pv = htonl(0x30000); /* protocol version 3.0 */
3736
3737 packet = (char*) calloc(1, packet_len);
3738
3739 memcpy(packet + 4, &pv, 4);
3740
3741 /* copy "user" */
3742 memcpy(packet + 8, "user", 4);
3743
3744 /* copy username */
3745 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3746
3747 free(curproxy->check_req);
3748 curproxy->check_req = packet;
3749 curproxy->check_len = packet_len;
3750
3751 packet_len = htonl(packet_len);
3752 memcpy(packet, &packet_len, 4);
3753 cur_arg += 2;
3754 } else {
3755 /* unknown suboption - catchall */
3756 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3757 file, linenum, args[0], args[1]);
3758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
3760 }
3761 } /* end while loop */
3762 }
3763 }
3764
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003765 else if (!strcmp(args[1], "redis-check")) {
3766 /* use REDIS PING request to check servers' health */
3767 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3768 err_code |= ERR_WARN;
3769
3770 free(curproxy->check_req);
3771 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003772 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003773 curproxy->options2 |= PR_O2_REDIS_CHK;
3774
3775 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3776 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3777 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3778 }
3779
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003780 else if (!strcmp(args[1], "mysql-check")) {
3781 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003782 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3783 err_code |= ERR_WARN;
3784
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003785 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003786 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003787 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003788 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003789
3790 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3791 * const char mysql40_client_auth_pkt[] = {
3792 * "\x0e\x00\x00" // packet length
3793 * "\x01" // packet number
3794 * "\x00\x00" // client capabilities
3795 * "\x00\x00\x01" // max packet
3796 * "haproxy\x00" // username (null terminated string)
3797 * "\x00" // filler (always 0x00)
3798 * "\x01\x00\x00" // packet length
3799 * "\x00" // packet number
3800 * "\x01" // COM_QUIT command
3801 * };
3802 */
3803
3804 if (*(args[2])) {
3805 int cur_arg = 2;
3806
3807 while (*(args[cur_arg])) {
3808 if (strcmp(args[cur_arg], "user") == 0) {
3809 char *mysqluser;
3810 int packetlen, reqlen, userlen;
3811
3812 /* suboption header - needs additional argument for it */
3813 if (*(args[cur_arg+1]) == 0) {
3814 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3815 file, linenum, args[0], args[1], args[cur_arg]);
3816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
3818 }
3819 mysqluser = args[cur_arg + 1];
3820 userlen = strlen(mysqluser);
3821 packetlen = userlen + 7;
3822 reqlen = packetlen + 9;
3823
3824 free(curproxy->check_req);
3825 curproxy->check_req = (char *)calloc(1, reqlen);
3826 curproxy->check_len = reqlen;
3827
3828 snprintf(curproxy->check_req, 4, "%c%c%c",
3829 ((unsigned char) packetlen & 0xff),
3830 ((unsigned char) (packetlen >> 8) & 0xff),
3831 ((unsigned char) (packetlen >> 16) & 0xff));
3832
3833 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003834 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003835 curproxy->check_req[8] = 1;
3836 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3837 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3838 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3839 cur_arg += 2;
3840 } else {
3841 /* unknown suboption - catchall */
3842 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3843 file, linenum, args[0], args[1]);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847 } /* end while loop */
3848 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003849 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003850 else if (!strcmp(args[1], "ldap-check")) {
3851 /* use LDAP request to check servers' health */
3852 free(curproxy->check_req);
3853 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003854 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003855 curproxy->options2 |= PR_O2_LDAP_CHK;
3856
3857 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3858 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3859 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3860 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003861 else if (!strcmp(args[1], "tcp-check")) {
3862 /* use raw TCPCHK send/expect to check servers' health */
3863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3864 err_code |= ERR_WARN;
3865
3866 free(curproxy->check_req);
3867 curproxy->check_req = NULL;
3868 curproxy->options2 &= ~PR_O2_CHK_ANY;
3869 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3870 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003871 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003872 int cur_arg;
3873
3874 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3875 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003876 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003877
Willy Tarreau87cf5142011-08-19 22:57:24 +02003878 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003879
3880 free(curproxy->fwdfor_hdr_name);
3881 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3882 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3883
3884 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3885 cur_arg = 2;
3886 while (*(args[cur_arg])) {
3887 if (!strcmp(args[cur_arg], "except")) {
3888 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003889 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003890 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3891 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003894 }
3895 /* flush useless bits */
3896 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003897 cur_arg += 2;
3898 } else if (!strcmp(args[cur_arg], "header")) {
3899 /* suboption header - needs additional argument for it */
3900 if (*(args[cur_arg+1]) == 0) {
3901 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3902 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003905 }
3906 free(curproxy->fwdfor_hdr_name);
3907 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3908 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3909 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003910 } else if (!strcmp(args[cur_arg], "if-none")) {
3911 curproxy->options &= ~PR_O_FF_ALWAYS;
3912 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003913 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003914 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003915 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003916 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003919 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003920 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003921 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003922 else if (!strcmp(args[1], "originalto")) {
3923 int cur_arg;
3924
3925 /* insert x-original-to field, but not for the IP address listed as an except.
3926 * set default options (ie: bitfield, header name, etc)
3927 */
3928
3929 curproxy->options |= PR_O_ORGTO;
3930
3931 free(curproxy->orgto_hdr_name);
3932 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3933 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3934
Willy Tarreau87cf5142011-08-19 22:57:24 +02003935 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003936 cur_arg = 2;
3937 while (*(args[cur_arg])) {
3938 if (!strcmp(args[cur_arg], "except")) {
3939 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003940 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 +02003941 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3942 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003945 }
3946 /* flush useless bits */
3947 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3948 cur_arg += 2;
3949 } else if (!strcmp(args[cur_arg], "header")) {
3950 /* suboption header - needs additional argument for it */
3951 if (*(args[cur_arg+1]) == 0) {
3952 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3953 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003956 }
3957 free(curproxy->orgto_hdr_name);
3958 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3959 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3960 cur_arg += 2;
3961 } else {
3962 /* unknown suboption - catchall */
3963 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3964 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003967 }
3968 } /* end while loop */
3969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 else {
3971 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003974 }
Willy Tarreau93893792009-07-23 13:19:11 +02003975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003977 else if (!strcmp(args[0], "default_backend")) {
3978 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003980
3981 if (*(args[1]) == 0) {
3982 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003985 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003986 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003987 curproxy->defbe.name = strdup(args[1]);
3988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003990 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003992
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003993 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3994 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 /* enable reconnections to dispatch */
3997 curproxy->options |= PR_O_REDISP;
3998 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003999 else if (!strcmp(args[0], "http-check")) {
4000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004002
4003 if (strcmp(args[1], "disable-on-404") == 0) {
4004 /* enable a graceful server shutdown on an HTTP 404 response */
4005 curproxy->options |= PR_O_DISABLE404;
4006 }
Willy Tarreauef781042010-01-27 11:53:01 +01004007 else if (strcmp(args[1], "send-state") == 0) {
4008 /* enable emission of the apparent state of a server in HTTP checks */
4009 curproxy->options2 |= PR_O2_CHK_SNDST;
4010 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004011 else if (strcmp(args[1], "expect") == 0) {
4012 const char *ptr_arg;
4013 int cur_arg;
4014
4015 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4016 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
4021 cur_arg = 2;
4022 /* consider exclamation marks, sole or at the beginning of a word */
4023 while (*(ptr_arg = args[cur_arg])) {
4024 while (*ptr_arg == '!') {
4025 curproxy->options2 ^= PR_O2_EXP_INV;
4026 ptr_arg++;
4027 }
4028 if (*ptr_arg)
4029 break;
4030 cur_arg++;
4031 }
4032 /* now ptr_arg points to the beginning of a word past any possible
4033 * exclamation mark, and cur_arg is the argument which holds this word.
4034 */
4035 if (strcmp(ptr_arg, "status") == 0) {
4036 if (!*(args[cur_arg + 1])) {
4037 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4038 file, linenum, args[0], args[1], ptr_arg);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004043 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004044 curproxy->expect_str = strdup(args[cur_arg + 1]);
4045 }
4046 else if (strcmp(ptr_arg, "string") == 0) {
4047 if (!*(args[cur_arg + 1])) {
4048 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4049 file, linenum, args[0], args[1], ptr_arg);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004054 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004055 curproxy->expect_str = strdup(args[cur_arg + 1]);
4056 }
4057 else if (strcmp(ptr_arg, "rstatus") == 0) {
4058 if (!*(args[cur_arg + 1])) {
4059 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4060 file, linenum, args[0], args[1], ptr_arg);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
4064 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004065 free(curproxy->expect_str);
4066 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4067 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004068 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4069 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4070 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4071 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075 }
4076 else if (strcmp(ptr_arg, "rstring") == 0) {
4077 if (!*(args[cur_arg + 1])) {
4078 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4079 file, linenum, args[0], args[1], ptr_arg);
4080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
4082 }
4083 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004084 free(curproxy->expect_str);
4085 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4086 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004087 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4088 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4089 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4090 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
4093 }
4094 }
4095 else {
4096 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4097 file, linenum, args[0], args[1], ptr_arg);
4098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
4100 }
4101 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004102 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004103 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 +02004104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004106 }
4107 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004108 else if (!strcmp(args[0], "tcp-check")) {
4109 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4110 err_code |= ERR_WARN;
4111
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004112 if (strcmp(args[1], "connect") == 0) {
4113 const char *ptr_arg;
4114 int cur_arg;
4115 struct tcpcheck_rule *tcpcheck;
4116 struct list *l;
4117
4118 /* check if first rule is also a 'connect' action */
4119 l = (struct list *)&curproxy->tcpcheck_rules;
4120 if (l->p != l->n) {
4121 tcpcheck = (struct tcpcheck_rule *)l->n;
4122 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4123 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4124 file, linenum);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128 }
4129
4130 cur_arg = 2;
4131 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4132 tcpcheck->action = TCPCHK_ACT_CONNECT;
4133
4134 /* parsing each parameters to fill up the rule */
4135 while (*(ptr_arg = args[cur_arg])) {
4136 /* tcp port */
4137 if (strcmp(args[cur_arg], "port") == 0) {
4138 if ( (atol(args[cur_arg + 1]) > 65535) ||
4139 (atol(args[cur_arg + 1]) < 1) ){
4140 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4141 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
4144 }
4145 tcpcheck->port = atol(args[cur_arg + 1]);
4146 cur_arg += 2;
4147 }
4148 /* send proxy protocol */
4149 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4150 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4151 cur_arg++;
4152 }
4153#ifdef USE_OPENSSL
4154 else if (strcmp(args[cur_arg], "ssl") == 0) {
4155 curproxy->options |= PR_O_TCPCHK_SSL;
4156 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4157 cur_arg++;
4158 }
4159#endif /* USE_OPENSSL */
4160 else {
4161#ifdef USE_OPENSSL
4162 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4163#else /* USE_OPENSSL */
4164 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4165#endif /* USE_OPENSSL */
4166 file, linenum, args[0], args[1], args[cur_arg]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170
4171 }
4172
4173 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4174 }
4175 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004176 if (! *(args[2]) ) {
4177 /* SEND string expected */
4178 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4179 file, linenum, args[0], args[1], args[2]);
4180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
4182 } else {
4183 struct tcpcheck_rule *tcpcheck;
4184
4185 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4186
4187 tcpcheck->action = TCPCHK_ACT_SEND;
4188 tcpcheck->string_len = strlen(args[2]);
4189 tcpcheck->string = strdup(args[2]);
4190 tcpcheck->expect_regex = NULL;
4191
4192 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4193 }
4194 }
4195 else if (strcmp(args[1], "send-binary") == 0) {
4196 if (! *(args[2]) ) {
4197 /* SEND binary string expected */
4198 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4199 file, linenum, args[0], args[1], args[2]);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 } else {
4203 struct tcpcheck_rule *tcpcheck;
4204 char *err = NULL;
4205
4206 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4207
4208 tcpcheck->action = TCPCHK_ACT_SEND;
4209 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4210 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4211 file, linenum, args[0], args[1], args[2], err);
4212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
4214 }
4215 tcpcheck->expect_regex = NULL;
4216
4217 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4218 }
4219 }
4220 else if (strcmp(args[1], "expect") == 0) {
4221 const char *ptr_arg;
4222 int cur_arg;
4223 int inverse = 0;
4224
4225 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4226 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
4230
4231 cur_arg = 2;
4232 /* consider exclamation marks, sole or at the beginning of a word */
4233 while (*(ptr_arg = args[cur_arg])) {
4234 while (*ptr_arg == '!') {
4235 inverse = !inverse;
4236 ptr_arg++;
4237 }
4238 if (*ptr_arg)
4239 break;
4240 cur_arg++;
4241 }
4242 /* now ptr_arg points to the beginning of a word past any possible
4243 * exclamation mark, and cur_arg is the argument which holds this word.
4244 */
4245 if (strcmp(ptr_arg, "binary") == 0) {
4246 if (!*(args[cur_arg + 1])) {
4247 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4248 file, linenum, args[0], args[1], ptr_arg);
4249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251 }
4252 struct tcpcheck_rule *tcpcheck;
4253 char *err = NULL;
4254
4255 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4256
4257 tcpcheck->action = TCPCHK_ACT_EXPECT;
4258 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4259 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4260 file, linenum, args[0], args[1], args[2], err);
4261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
4263 }
4264 tcpcheck->expect_regex = NULL;
4265 tcpcheck->inverse = inverse;
4266
4267 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4268 }
4269 else if (strcmp(ptr_arg, "string") == 0) {
4270 if (!*(args[cur_arg + 1])) {
4271 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4272 file, linenum, args[0], args[1], ptr_arg);
4273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 }
4276 struct tcpcheck_rule *tcpcheck;
4277
4278 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4279
4280 tcpcheck->action = TCPCHK_ACT_EXPECT;
4281 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4282 tcpcheck->string = strdup(args[cur_arg + 1]);
4283 tcpcheck->expect_regex = NULL;
4284 tcpcheck->inverse = inverse;
4285
4286 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4287 }
4288 else if (strcmp(ptr_arg, "rstring") == 0) {
4289 if (!*(args[cur_arg + 1])) {
4290 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4291 file, linenum, args[0], args[1], ptr_arg);
4292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
4294 }
4295 struct tcpcheck_rule *tcpcheck;
4296
4297 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4298
4299 tcpcheck->action = TCPCHK_ACT_EXPECT;
4300 tcpcheck->string_len = 0;
4301 tcpcheck->string = NULL;
4302 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4303 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4304 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4305 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
4309 tcpcheck->inverse = inverse;
4310
4311 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4312 }
4313 else {
4314 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4315 file, linenum, args[0], args[1], ptr_arg);
4316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319 }
4320 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004321 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
4324 }
4325 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004326 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004327 if (curproxy == &defproxy) {
4328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004331 }
4332
Willy Tarreaub80c2302007-11-30 20:51:32 +01004333 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004335
4336 if (strcmp(args[1], "fail") == 0) {
4337 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004338 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004339 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4340 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004343 }
4344
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004345 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4346 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4347 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004350 }
4351 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4352 }
4353 else {
4354 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004357 }
4358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359#ifdef TPROXY
4360 else if (!strcmp(args[0], "transparent")) {
4361 /* enable transparent proxy connections */
4362 curproxy->options |= PR_O_TRANSP;
4363 }
4364#endif
4365 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004366 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004368
Willy Tarreaubaaee002006-06-26 02:48:02 +02004369 if (*(args[1]) == 0) {
4370 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 }
4374 curproxy->maxconn = atol(args[1]);
4375 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004376 else if (!strcmp(args[0], "backlog")) { /* backlog */
4377 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004379
4380 if (*(args[1]) == 0) {
4381 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004384 }
4385 curproxy->backlog = atol(args[1]);
4386 }
Willy Tarreau86034312006-12-29 00:10:33 +01004387 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004388 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004389 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004390
Willy Tarreau86034312006-12-29 00:10:33 +01004391 if (*(args[1]) == 0) {
4392 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004395 }
4396 curproxy->fullconn = atol(args[1]);
4397 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4399 if (*(args[1]) == 0) {
4400 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004404 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4405 if (err) {
4406 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4407 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004410 }
4411 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 }
4413 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004414 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004415 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004416 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004417
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 if (curproxy == &defproxy) {
4419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004423 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004425
Willy Tarreau902636f2013-03-10 19:44:48 +01004426 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004427 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004428 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004429 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004430 goto out;
4431 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004432
4433 proto = protocol_by_family(sk->ss_family);
4434 if (!proto || !proto->connect) {
4435 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4436 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
4439 }
4440
4441 if (port1 != port2) {
4442 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4443 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004447
4448 if (!port1) {
4449 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4450 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
4453 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004454
Willy Tarreaud5191e72010-02-09 20:50:45 +01004455 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004456 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 }
4458 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004459 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004461
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004462 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4463 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004468 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004469 /**
4470 * The syntax for hash-type config element is
4471 * hash-type {map-based|consistent} [[<algo>] avalanche]
4472 *
4473 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4474 */
4475 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004476
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004477 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4478 err_code |= ERR_WARN;
4479
4480 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004481 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4482 }
4483 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004484 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4485 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004486 else if (strcmp(args[1], "avalanche") == 0) {
4487 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]);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004490 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004491 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004492 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
Bhaskar98634f02013-10-29 23:30:51 -04004496
4497 /* set the hash function to use */
4498 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004499 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004500 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004501
4502 /* if consistent with no argument, then avalanche modifier is also applied */
4503 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4504 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004505 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004506 /* set the hash function */
4507 if (!strcmp(args[2], "sdbm")) {
4508 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4509 }
4510 else if (!strcmp(args[2], "djb2")) {
4511 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004512 } else if (!strcmp(args[2], "wt6")) {
4513 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004514 }
4515 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004516 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 -05004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
4519 }
4520
4521 /* set the hash modifier */
4522 if (!strcmp(args[3], "avalanche")) {
4523 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4524 }
4525 else if (*args[3]) {
4526 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
4529 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004530 }
William Lallemanda73203e2012-03-12 12:48:57 +01004531 }
William Lallemanda73203e2012-03-12 12:48:57 +01004532 else if (strcmp(args[0], "unique-id-format") == 0) {
4533 if (!*(args[1])) {
4534 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
William Lallemand3203ff42012-11-11 17:30:56 +01004538 if (*(args[2])) {
4539 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
4542 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004543 free(curproxy->conf.uniqueid_format_string);
4544 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004545
Willy Tarreau62a61232013-04-12 18:13:46 +02004546 free(curproxy->conf.uif_file);
4547 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4548 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004549 }
William Lallemanda73203e2012-03-12 12:48:57 +01004550
4551 else if (strcmp(args[0], "unique-id-header") == 0) {
4552 if (!*(args[1])) {
4553 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
4556 }
4557 free(curproxy->header_unique_id);
4558 curproxy->header_unique_id = strdup(args[1]);
4559 }
4560
William Lallemand723b73a2012-02-08 16:37:49 +01004561 else if (strcmp(args[0], "log-format") == 0) {
4562 if (!*(args[1])) {
4563 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
4566 }
William Lallemand3203ff42012-11-11 17:30:56 +01004567 if (*(args[2])) {
4568 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
4571 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004572
Willy Tarreau62a61232013-04-12 18:13:46 +02004573 if (curproxy->conf.logformat_string != default_http_log_format &&
4574 curproxy->conf.logformat_string != default_tcp_log_format &&
4575 curproxy->conf.logformat_string != clf_http_log_format)
4576 free(curproxy->conf.logformat_string);
4577 curproxy->conf.logformat_string = strdup(args[1]);
4578
4579 free(curproxy->conf.lfs_file);
4580 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4581 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004582
4583 /* get a chance to improve log-format error reporting by
4584 * reporting the correct line-number when possible.
4585 */
4586 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4587 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4588 file, linenum, curproxy->id);
4589 err_code |= ERR_WARN;
4590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
William Lallemand723b73a2012-02-08 16:37:49 +01004592
William Lallemand0f99e342011-10-12 17:50:54 +02004593 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4594 /* delete previous herited or defined syslog servers */
4595 struct logsrv *back;
4596
4597 if (*(args[1]) != 0) {
4598 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
4602
William Lallemand723b73a2012-02-08 16:37:49 +01004603 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4604 LIST_DEL(&tmplogsrv->list);
4605 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004606 }
4607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004609 struct logsrv *logsrv;
4610
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004612 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004613 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004614 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004615 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004616 LIST_INIT(&node->list);
4617 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
4620 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004621 struct sockaddr_storage *sk;
4622 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004623
4624 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625
William Lallemand0f99e342011-10-12 17:50:54 +02004626 logsrv->facility = get_log_facility(args[2]);
4627 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
4631
Willy Tarreaubaaee002006-06-26 02:48:02 +02004632 }
4633
William Lallemand0f99e342011-10-12 17:50:54 +02004634 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004636 logsrv->level = get_log_level(args[3]);
4637 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004638 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 }
4643 }
4644
William Lallemand0f99e342011-10-12 17:50:54 +02004645 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004646 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004647 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004648 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004649 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
4652
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004653 }
4654 }
4655
Willy Tarreau902636f2013-03-10 19:44:48 +01004656 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004657 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004658 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004660 goto out;
4661 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004662
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004663 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004664
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004665 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004666 if (port1 != port2) {
4667 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4668 file, linenum, args[0], args[1]);
4669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
4671 }
4672
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004673 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004674 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 }
William Lallemand0f99e342011-10-12 17:50:54 +02004676
4677 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 }
4679 else {
4680 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4681 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004682 err_code |= ERR_ALERT | ERR_FATAL;
4683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 }
4685 }
4686 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004687 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004688 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004689 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004690 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004691
Willy Tarreau977b8e42006-12-29 14:19:17 +01004692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004693 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004694
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004696 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4697 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004701
4702 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004703 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4704 free(curproxy->conn_src.iface_name);
4705 curproxy->conn_src.iface_name = NULL;
4706 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004707
Willy Tarreau902636f2013-03-10 19:44:48 +01004708 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004709 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004710 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004711 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004712 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004713 goto out;
4714 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004715
4716 proto = protocol_by_family(sk->ss_family);
4717 if (!proto || !proto->connect) {
4718 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004719 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
4722 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004723
4724 if (port1 != port2) {
4725 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4726 file, linenum, args[0], args[1]);
4727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729 }
4730
Willy Tarreauef9a3602012-12-08 22:29:20 +01004731 curproxy->conn_src.source_addr = *sk;
4732 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004733
4734 cur_arg = 2;
4735 while (*(args[cur_arg])) {
4736 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004737#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4738#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004739 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004740 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4741 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004744 }
4745#endif
4746 if (!*args[cur_arg + 1]) {
4747 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4748 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004751 }
4752
4753 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004754 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4755 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004756 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004757 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4758 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004759 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4760 char *name, *end;
4761
4762 name = args[cur_arg+1] + 7;
4763 while (isspace(*name))
4764 name++;
4765
4766 end = name;
4767 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4768 end++;
4769
Willy Tarreauef9a3602012-12-08 22:29:20 +01004770 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4771 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4772 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4773 curproxy->conn_src.bind_hdr_len = end - name;
4774 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4775 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4776 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004777
4778 /* now look for an occurrence number */
4779 while (isspace(*end))
4780 end++;
4781 if (*end == ',') {
4782 end++;
4783 name = end;
4784 if (*end == '-')
4785 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004786 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004787 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004788 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004789 }
4790
Willy Tarreauef9a3602012-12-08 22:29:20 +01004791 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004792 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4793 " occurrences values smaller than %d.\n",
4794 file, linenum, MAX_HDR_HISTORY);
4795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
4797 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004798 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004799 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004800
Willy Tarreau902636f2013-03-10 19:44:48 +01004801 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004802 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004803 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004804 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004805 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004806 goto out;
4807 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004808
4809 proto = protocol_by_family(sk->ss_family);
4810 if (!proto || !proto->connect) {
4811 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4812 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004816
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004817 if (port1 != port2) {
4818 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4819 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
4822 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004823 curproxy->conn_src.tproxy_addr = *sk;
4824 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004825 }
4826 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004827#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004828 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004829#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004830#else /* no TPROXY support */
4831 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004832 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004835#endif
4836 cur_arg += 2;
4837 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004838 }
4839
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004840 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4841#ifdef SO_BINDTODEVICE
4842 if (!*args[cur_arg + 1]) {
4843 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4844 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004847 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004848 free(curproxy->conn_src.iface_name);
4849 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4850 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004851 global.last_checks |= LSTCHK_NETADM;
4852#else
4853 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4854 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004857#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004858 cur_arg += 2;
4859 continue;
4860 }
4861 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004862 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004867 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4868 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4869 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004874 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004880
4881 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004882 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004883 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004884 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 }
4887 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004888 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004889 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004890 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004891 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
4894 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004895 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004896 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004897 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004898 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
4901 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004903 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004904 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
4908 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004910 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004911 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004915 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004917 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004918 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004920 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004921 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004922 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004924 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004925 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004927 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004928 }
4929 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004931 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004932 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004934 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943
4944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004945 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004946 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
4950 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004952 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004953 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
4957 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004958 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004959 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004960 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
4964 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004966 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004967 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004970 }
4971 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004973 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004974 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004978 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004980 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004981 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004983 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004986 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004987
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 if (curproxy == &defproxy) {
4989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004993 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004994 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 if (*(args[1]) == 0) {
4997 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005001
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005002 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005003 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5004 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5005 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
5008 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005009 err_code |= warnif_cond_conflicts(cond,
5010 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5011 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005012 }
5013 else if (*args[2]) {
5014 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5015 file, linenum, args[0], args[2]);
5016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
5018 }
5019
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005020 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005021 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005022 wl->s = strdup(args[1]);
5023 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005024 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
5026 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5029 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005033
Willy Tarreauade5ec42010-01-28 19:33:49 +01005034 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005035 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005036 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005037 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 }
5040 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005041 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005042 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005043 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
5047 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005048 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005049 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005050 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005051 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
5054 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005055 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 }
5061
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005063 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005064 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005065 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 }
5068 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005070 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005071 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005072 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 }
5075 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005077 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005078 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005079 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 }
5082 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005083 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005084
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 if (curproxy == &defproxy) {
5086 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005090 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 if (*(args[1]) == 0) {
5094 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 }
5098
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005099 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005100 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5101 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5102 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
5105 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005106 err_code |= warnif_cond_conflicts(cond,
5107 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5108 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005109 }
5110 else if (*args[2]) {
5111 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5112 file, linenum, args[0], args[2]);
5113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
5115 }
5116
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005117 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005118 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005119 wl->s = strdup(args[1]);
5120 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
5122 else if (!strcmp(args[0], "errorloc") ||
5123 !strcmp(args[0], "errorloc302") ||
5124 !strcmp(args[0], "errorloc303")) { /* error location */
5125 int errnum, errlen;
5126 char *err;
5127
Willy Tarreau977b8e42006-12-29 14:19:17 +01005128 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005130
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005132 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 }
5136
5137 errnum = atol(args[1]);
5138 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005139 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5140 err = malloc(errlen);
5141 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005143 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5144 err = malloc(errlen);
5145 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 }
5147
Willy Tarreau0f772532006-12-23 20:51:41 +01005148 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5149 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005150 chunk_destroy(&curproxy->errmsg[rc]);
5151 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005152 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005155
5156 if (rc >= HTTP_ERR_SIZE) {
5157 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5158 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 free(err);
5160 }
5161 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005162 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5163 int errnum, errlen, fd;
5164 char *err;
5165 struct stat stat;
5166
5167 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005168 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005169
5170 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005171 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005174 }
5175
5176 fd = open(args[2], O_RDONLY);
5177 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5178 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5179 file, linenum, args[2], args[1]);
5180 if (fd >= 0)
5181 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005184 }
5185
Willy Tarreau27a674e2009-08-17 07:23:33 +02005186 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005187 errlen = stat.st_size;
5188 } else {
5189 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005190 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005192 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005193 }
5194
5195 err = malloc(errlen); /* malloc() must succeed during parsing */
5196 errnum = read(fd, err, errlen);
5197 if (errnum != errlen) {
5198 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5199 file, linenum, args[2], args[1]);
5200 close(fd);
5201 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005204 }
5205 close(fd);
5206
5207 errnum = atol(args[1]);
5208 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5209 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005210 chunk_destroy(&curproxy->errmsg[rc]);
5211 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005212 break;
5213 }
5214 }
5215
5216 if (rc >= HTTP_ERR_SIZE) {
5217 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5218 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005220 free(err);
5221 }
5222 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005223 else if (!strcmp(args[0], "compression")) {
5224 struct comp *comp;
5225 if (curproxy->comp == NULL) {
5226 comp = calloc(1, sizeof(struct comp));
5227 curproxy->comp = comp;
5228 } else {
5229 comp = curproxy->comp;
5230 }
5231
5232 if (!strcmp(args[1], "algo")) {
5233 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005234 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005235
William Lallemand82fe75c2012-10-23 10:25:10 +02005236 cur_arg = 2;
5237 if (!*args[cur_arg]) {
5238 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5239 file, linenum, args[0]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243 while (*(args[cur_arg])) {
5244 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5245 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5246 file, linenum, args[0], args[cur_arg]);
5247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
William Lallemand552df672012-11-07 13:21:47 +01005250 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5251 curproxy->comp->algos->end(&ctx);
5252 } else {
5253 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5254 file, linenum, args[0], args[cur_arg]);
5255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
5257 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005258 cur_arg ++;
5259 continue;
5260 }
5261 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005262 else if (!strcmp(args[1], "offload")) {
5263 comp->offload = 1;
5264 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005265 else if (!strcmp(args[1], "type")) {
5266 int cur_arg;
5267 cur_arg = 2;
5268 if (!*args[cur_arg]) {
5269 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5270 file, linenum, args[0]);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274 while (*(args[cur_arg])) {
5275 comp_append_type(comp, args[cur_arg]);
5276 cur_arg ++;
5277 continue;
5278 }
5279 }
5280 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005281 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005282 file, linenum, args[0]);
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
5286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005288 struct cfg_kw_list *kwl;
5289 int index;
5290
5291 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5292 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5293 if (kwl->kw[index].section != CFG_LISTEN)
5294 continue;
5295 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5296 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005297 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005298 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005299 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005302 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005303 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005304 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005305 err_code |= ERR_WARN;
5306 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005307 }
Willy Tarreau93893792009-07-23 13:19:11 +02005308 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005309 }
5310 }
5311 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005312
Willy Tarreau6daf3432008-01-22 16:44:08 +01005313 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
Willy Tarreau93893792009-07-23 13:19:11 +02005317 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005318 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005319 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320}
5321
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005322int
5323cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5324{
5325
5326 int err_code = 0;
5327 const char *err;
5328
5329 if (!strcmp(args[0], "userlist")) { /* new userlist */
5330 struct userlist *newul;
5331
5332 if (!*args[1]) {
5333 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5334 file, linenum, args[0]);
5335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
5338
5339 err = invalid_char(args[1]);
5340 if (err) {
5341 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5342 file, linenum, *err, args[0], args[1]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346
5347 for (newul = userlist; newul; newul = newul->next)
5348 if (!strcmp(newul->name, args[1])) {
5349 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5350 file, linenum, args[1]);
5351 err_code |= ERR_WARN;
5352 goto out;
5353 }
5354
5355 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5356 if (!newul) {
5357 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5358 err_code |= ERR_ALERT | ERR_ABORT;
5359 goto out;
5360 }
5361
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005362 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005363 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005364 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5365 err_code |= ERR_ALERT | ERR_ABORT;
5366 goto out;
5367 }
5368
5369 newul->next = userlist;
5370 userlist = newul;
5371
5372 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005373 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005374 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005375 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005376
5377 if (!*args[1]) {
5378 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5379 file, linenum, args[0]);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383
5384 err = invalid_char(args[1]);
5385 if (err) {
5386 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5387 file, linenum, *err, args[0], args[1]);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
5391
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005392 for (ag = userlist->groups; ag; ag = ag->next)
5393 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005394 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5395 file, linenum, args[1], userlist->name);
5396 err_code |= ERR_ALERT;
5397 goto out;
5398 }
5399
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005400 ag = calloc(1, sizeof(*ag));
5401 if (!ag) {
5402 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5403 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005404 goto out;
5405 }
5406
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005407 ag->name = strdup(args[1]);
5408 if (!ag) {
5409 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5410 err_code |= ERR_ALERT | ERR_ABORT;
5411 goto out;
5412 }
5413
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005414 cur_arg = 2;
5415
5416 while (*args[cur_arg]) {
5417 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005418 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005419 cur_arg += 2;
5420 continue;
5421 } else {
5422 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5423 file, linenum, args[0]);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
5427 }
5428
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005429 ag->next = userlist->groups;
5430 userlist->groups = ag;
5431
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005432 } else if (!strcmp(args[0], "user")) { /* new user */
5433 struct auth_users *newuser;
5434 int cur_arg;
5435
5436 if (!*args[1]) {
5437 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5438 file, linenum, args[0]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442
5443 for (newuser = userlist->users; newuser; newuser = newuser->next)
5444 if (!strcmp(newuser->user, args[1])) {
5445 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5446 file, linenum, args[1], userlist->name);
5447 err_code |= ERR_ALERT;
5448 goto out;
5449 }
5450
5451 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5452 if (!newuser) {
5453 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5454 err_code |= ERR_ALERT | ERR_ABORT;
5455 goto out;
5456 }
5457
5458 newuser->user = strdup(args[1]);
5459
5460 newuser->next = userlist->users;
5461 userlist->users = newuser;
5462
5463 cur_arg = 2;
5464
5465 while (*args[cur_arg]) {
5466 if (!strcmp(args[cur_arg], "password")) {
5467#ifndef CONFIG_HAP_CRYPT
5468 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5469 file, linenum);
5470 err_code |= ERR_ALERT;
5471#endif
5472 newuser->pass = strdup(args[cur_arg + 1]);
5473 cur_arg += 2;
5474 continue;
5475 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5476 newuser->pass = strdup(args[cur_arg + 1]);
5477 newuser->flags |= AU_O_INSECURE;
5478 cur_arg += 2;
5479 continue;
5480 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005481 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005482 cur_arg += 2;
5483 continue;
5484 } else {
5485 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5486 file, linenum, args[0]);
5487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
5489 }
5490 }
5491 } else {
5492 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5493 err_code |= ERR_ALERT | ERR_FATAL;
5494 }
5495
5496out:
5497 return err_code;
5498}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499
5500/*
5501 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005502 * Returns the error code, 0 if OK, or any combination of :
5503 * - ERR_ABORT: must abort ASAP
5504 * - ERR_FATAL: we can continue parsing but not start the service
5505 * - ERR_WARN: a warning has been emitted
5506 * - ERR_ALERT: an alert has been emitted
5507 * Only the two first ones can stop processing, the two others are just
5508 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005510int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005512 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005513 FILE *f;
5514 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005515 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005516 struct cfg_section *cs = NULL;
5517 struct cfg_section *ics;
5518
5519 /* Register internal sections */
5520 if (!cfg_register_section("listen", cfg_parse_listen) ||
5521 !cfg_register_section("frontend", cfg_parse_listen) ||
5522 !cfg_register_section("backend", cfg_parse_listen) ||
5523 !cfg_register_section("ruleset", cfg_parse_listen) ||
5524 !cfg_register_section("defaults", cfg_parse_listen) ||
5525 !cfg_register_section("global", cfg_parse_global) ||
5526 !cfg_register_section("userlist", cfg_parse_users) ||
5527 !cfg_register_section("peers", cfg_parse_peers))
5528 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 if ((f=fopen(file,"r")) == NULL)
5531 return -1;
5532
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005533 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005534 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005535 char *end;
5536 char *args[MAX_LINE_ARGS + 1];
5537 char *line = thisline;
5538
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 linenum++;
5540
5541 end = line + strlen(line);
5542
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005543 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5544 /* Check if we reached the limit and the last char is not \n.
5545 * Watch out for the last line without the terminating '\n'!
5546 */
5547 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005548 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005549 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005550 }
5551
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005553 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 line++;
5555
5556 arg = 0;
5557 args[arg] = line;
5558
5559 while (*line && arg < MAX_LINE_ARGS) {
5560 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5561 * C equivalent value. Other combinations left unchanged (eg: \1).
5562 */
5563 if (*line == '\\') {
5564 int skip = 0;
5565 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5566 *line = line[1];
5567 skip = 1;
5568 }
5569 else if (line[1] == 'r') {
5570 *line = '\r';
5571 skip = 1;
5572 }
5573 else if (line[1] == 'n') {
5574 *line = '\n';
5575 skip = 1;
5576 }
5577 else if (line[1] == 't') {
5578 *line = '\t';
5579 skip = 1;
5580 }
5581 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005582 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 unsigned char hex1, hex2;
5584 hex1 = toupper(line[2]) - '0';
5585 hex2 = toupper(line[3]) - '0';
5586 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5587 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5588 *line = (hex1<<4) + hex2;
5589 skip = 3;
5590 }
5591 else {
5592 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
5595 }
5596 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005597 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 end -= skip;
5599 }
5600 line++;
5601 }
5602 else if (*line == '#' || *line == '\n' || *line == '\r') {
5603 /* end of string, end of loop */
5604 *line = 0;
5605 break;
5606 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005607 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005609 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005610 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611 line++;
5612 args[++arg] = line;
5613 }
5614 else {
5615 line++;
5616 }
5617 }
5618
5619 /* empty line */
5620 if (!**args)
5621 continue;
5622
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005623 if (*line) {
5624 /* we had to stop due to too many args.
5625 * Let's terminate the string, print the offending part then cut the
5626 * last arg.
5627 */
5628 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5629 line++;
5630 *line = '\0';
5631
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005632 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005633 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005634 err_code |= ERR_ALERT | ERR_FATAL;
5635 args[arg] = line;
5636 }
5637
Willy Tarreau540abe42007-05-02 20:50:16 +02005638 /* zero out remaining args and ensure that at least one entry
5639 * is zeroed out.
5640 */
5641 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005642 args[arg] = line;
5643 }
5644
Willy Tarreau3842f002009-06-14 11:39:52 +02005645 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005646 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005647 char *tmp;
5648
Willy Tarreau3842f002009-06-14 11:39:52 +02005649 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005650 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005651 for (arg=0; *args[arg+1]; arg++)
5652 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005653 *tmp = '\0'; // fix the next arg to \0
5654 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005655 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005656 else if (!strcmp(args[0], "default")) {
5657 kwm = KWM_DEF;
5658 for (arg=0; *args[arg+1]; arg++)
5659 args[arg] = args[arg+1]; // shift args after inversion
5660 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005661
William Lallemand0f99e342011-10-12 17:50:54 +02005662 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5663 strcmp(args[0], "log") != 0) {
5664 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005665 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005666 }
5667
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005668 /* detect section start */
5669 list_for_each_entry(ics, &sections, list) {
5670 if (strcmp(args[0], ics->section_name) == 0) {
5671 cursection = ics->section_name;
5672 cs = ics;
5673 break;
5674 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005675 }
5676
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005678 if (cs)
5679 err_code |= cs->section_parser(file, linenum, args, kwm);
5680 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005681 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005684
5685 if (err_code & ERR_ABORT)
5686 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005688 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005690 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005691}
5692
Willy Tarreaubb925012009-07-23 13:36:36 +02005693/*
5694 * Returns the error code, 0 if OK, or any combination of :
5695 * - ERR_ABORT: must abort ASAP
5696 * - ERR_FATAL: we can continue parsing but not start the service
5697 * - ERR_WARN: a warning has been emitted
5698 * - ERR_ALERT: an alert has been emitted
5699 * Only the two first ones can stop processing, the two others are just
5700 * indicators.
5701 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005702int check_config_validity()
5703{
5704 int cfgerr = 0;
5705 struct proxy *curproxy = NULL;
5706 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005707 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005708 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005709 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005711 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 /*
5713 * Now, check for the integrity of all that we have collected.
5714 */
5715
5716 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005717 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718
Willy Tarreau193b8c62012-11-22 00:17:38 +01005719 if (!global.tune.max_http_hdr)
5720 global.tune.max_http_hdr = MAX_HTTP_HDR;
5721
5722 if (!global.tune.cookie_len)
5723 global.tune.cookie_len = CAPTURE_LEN;
5724
5725 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5726
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005727 /* Post initialisation of the users and groups lists. */
5728 err_code = userlist_postinit();
5729 if (err_code != ERR_NONE)
5730 goto out;
5731
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005732 /* first, we will invert the proxy list order */
5733 curproxy = NULL;
5734 while (proxy) {
5735 struct proxy *next;
5736
5737 next = proxy->next;
5738 proxy->next = curproxy;
5739 curproxy = proxy;
5740 if (!next)
5741 break;
5742 proxy = next;
5743 }
5744
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005746 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005747 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005748 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005749 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005750 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005751 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005752 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005753
Willy Tarreau050536d2012-10-04 08:47:34 +02005754 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005755 /* proxy ID not set, use automatic numbering with first
5756 * spare entry starting with next_pxid.
5757 */
5758 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5759 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5760 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005761 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005762 next_pxid++;
5763
Willy Tarreau55ea7572007-06-17 19:56:27 +02005764
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005766 /* ensure we don't keep listeners uselessly bound */
5767 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 curproxy = curproxy->next;
5769 continue;
5770 }
5771
Willy Tarreau16a21472012-11-19 12:39:59 +01005772 /* number of processes this proxy is bound to */
5773 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5774
Willy Tarreauff01a212009-03-15 13:46:16 +01005775 switch (curproxy->mode) {
5776 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005777 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005778 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005779 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5780 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005781 cfgerr++;
5782 }
5783
5784 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005785 Warning("config : servers will be ignored for %s '%s'.\n",
5786 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005787 break;
5788
5789 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005790 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005791 break;
5792
5793 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005794 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005795 break;
5796 }
5797
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005798 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005799 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005800 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005801 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5802 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005803 cfgerr++;
5804 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005806 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005807 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5808 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005809 cfgerr++;
5810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005812 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005813 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5814 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005815 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005816 }
5817 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005818 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005819 /* If no LB algo is set in a backend, and we're not in
5820 * transparent mode, dispatch mode nor proxy mode, we
5821 * want to use balance roundrobin by default.
5822 */
5823 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5824 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 }
5826 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005827
Willy Tarreau1620ec32011-08-06 17:05:02 +02005828 if (curproxy->options & PR_O_DISPATCH)
5829 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5830 else if (curproxy->options & PR_O_HTTP_PROXY)
5831 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5832 else if (curproxy->options & PR_O_TRANSP)
5833 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005834
Willy Tarreau1620ec32011-08-06 17:05:02 +02005835 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5836 if (curproxy->options & PR_O_DISABLE404) {
5837 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5838 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5839 err_code |= ERR_WARN;
5840 curproxy->options &= ~PR_O_DISABLE404;
5841 }
5842 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5843 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5844 "send-state", proxy_type_str(curproxy), curproxy->id);
5845 err_code |= ERR_WARN;
5846 curproxy->options &= ~PR_O2_CHK_SNDST;
5847 }
Willy Tarreauef781042010-01-27 11:53:01 +01005848 }
5849
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005850 /* if a default backend was specified, let's find it */
5851 if (curproxy->defbe.name) {
5852 struct proxy *target;
5853
Alex Williams96532db2009-11-01 21:27:13 -05005854 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005855 if (!target) {
5856 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5857 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005858 cfgerr++;
5859 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005860 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5861 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005862 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005863 } else {
5864 free(curproxy->defbe.name);
5865 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005866 /* we force the backend to be present on at least all of
5867 * the frontend's processes.
5868 */
5869 target->bind_proc = curproxy->bind_proc ?
5870 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005871
5872 /* Emit a warning if this proxy also has some servers */
5873 if (curproxy->srv) {
5874 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5875 curproxy->id);
5876 err_code |= ERR_WARN;
5877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
5879 }
5880
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005881 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005882 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5883 /* map jump target for ACT_SETBE in req_rep chain */
5884 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005885 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005886 struct proxy *target;
5887
Willy Tarreaua496b602006-12-17 23:15:24 +01005888 if (exp->action != ACT_SETBE)
5889 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005890
Alex Williams96532db2009-11-01 21:27:13 -05005891 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005892 if (!target) {
5893 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5894 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005895 cfgerr++;
5896 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005897 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5898 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005899 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005900 } else {
5901 free((void *)exp->replace);
5902 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005903 /* we force the backend to be present on at least all of
5904 * the frontend's processes.
5905 */
5906 target->bind_proc = curproxy->bind_proc ?
5907 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005908 }
5909 }
5910 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005911
5912 /* find the target proxy for 'use_backend' rules */
5913 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005914 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005915 struct logformat_node *node;
5916 char *pxname;
5917
5918 /* Try to parse the string as a log format expression. If the result
5919 * of the parsing is only one entry containing a simple string, then
5920 * it's a standard string corresponding to a static rule, thus the
5921 * parsing is cancelled and be.name is restored to be resolved.
5922 */
5923 pxname = rule->be.name;
5924 LIST_INIT(&rule->be.expr);
5925 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
5926 curproxy->conf.args.file, curproxy->conf.args.line);
5927 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
5928
5929 if (!LIST_ISEMPTY(&rule->be.expr)) {
5930 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
5931 rule->dynamic = 1;
5932 free(pxname);
5933 continue;
5934 }
5935 /* simple string: free the expression and fall back to static rule */
5936 free(node->arg);
5937 free(node);
5938 }
5939
5940 rule->dynamic = 0;
5941 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005942
Alex Williams96532db2009-11-01 21:27:13 -05005943 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005944
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005945 if (!target) {
5946 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5947 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005948 cfgerr++;
5949 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005950 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5951 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005952 cfgerr++;
5953 } else {
5954 free((void *)rule->be.name);
5955 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005956 /* we force the backend to be present on at least all of
5957 * the frontend's processes.
5958 */
5959 target->bind_proc = curproxy->bind_proc ?
5960 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005961 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005962 }
5963
5964 /* find the target proxy for 'use_backend' rules */
5965 list_for_each_entry(srule, &curproxy->server_rules, list) {
5966 struct server *target = findserver(curproxy, srule->srv.name);
5967
5968 if (!target) {
5969 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5970 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5971 cfgerr++;
5972 continue;
5973 }
5974 free((void *)srule->srv.name);
5975 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005976 }
5977
Emeric Brunb982a3d2010-01-04 15:45:53 +01005978 /* find the target table for 'stick' rules */
5979 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5980 struct proxy *target;
5981
Emeric Brun1d33b292010-01-04 15:47:17 +01005982 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5983 if (mrule->flags & STK_IS_STORE)
5984 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5985
Emeric Brunb982a3d2010-01-04 15:45:53 +01005986 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005987 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005988 else
5989 target = curproxy;
5990
5991 if (!target) {
5992 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5993 curproxy->id, mrule->table.name);
5994 cfgerr++;
5995 }
5996 else if (target->table.size == 0) {
5997 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5998 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5999 cfgerr++;
6000 }
Willy Tarreau12785782012-04-27 21:37:17 +02006001 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6002 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006003 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6004 cfgerr++;
6005 }
6006 else {
6007 free((void *)mrule->table.name);
6008 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006009 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006010 }
6011 }
6012
6013 /* find the target table for 'store response' rules */
6014 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6015 struct proxy *target;
6016
Emeric Brun1d33b292010-01-04 15:47:17 +01006017 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6018
Emeric Brunb982a3d2010-01-04 15:45:53 +01006019 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006020 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006021 else
6022 target = curproxy;
6023
6024 if (!target) {
6025 Alert("Proxy '%s': unable to find store table '%s'.\n",
6026 curproxy->id, mrule->table.name);
6027 cfgerr++;
6028 }
6029 else if (target->table.size == 0) {
6030 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6031 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6032 cfgerr++;
6033 }
Willy Tarreau12785782012-04-27 21:37:17 +02006034 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6035 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006036 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6037 cfgerr++;
6038 }
6039 else {
6040 free((void *)mrule->table.name);
6041 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006042 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006043 }
6044 }
6045
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006046 /* find the target table for 'tcp-request' layer 4 rules */
6047 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6048 struct proxy *target;
6049
Willy Tarreaub4c84932013-07-23 19:15:30 +02006050 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006051 continue;
6052
6053 if (trule->act_prm.trk_ctr.table.n)
6054 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6055 else
6056 target = curproxy;
6057
6058 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006059 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6060 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006061 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006062 cfgerr++;
6063 }
6064 else if (target->table.size == 0) {
6065 Alert("Proxy '%s': table '%s' used but not configured.\n",
6066 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6067 cfgerr++;
6068 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006069 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6070 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6071 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006072 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006073 cfgerr++;
6074 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006075 else {
6076 free(trule->act_prm.trk_ctr.table.n);
6077 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006078 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006079 * to pass a list of counters to track and allocate them right here using
6080 * stktable_alloc_data_type().
6081 */
6082 }
6083 }
6084
Willy Tarreaud1f96522010-08-03 19:34:32 +02006085 /* find the target table for 'tcp-request' layer 6 rules */
6086 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6087 struct proxy *target;
6088
Willy Tarreaub4c84932013-07-23 19:15:30 +02006089 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006090 continue;
6091
6092 if (trule->act_prm.trk_ctr.table.n)
6093 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6094 else
6095 target = curproxy;
6096
6097 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006098 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6099 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006100 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006101 cfgerr++;
6102 }
6103 else if (target->table.size == 0) {
6104 Alert("Proxy '%s': table '%s' used but not configured.\n",
6105 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6106 cfgerr++;
6107 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006108 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6109 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6110 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006111 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006112 cfgerr++;
6113 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006114 else {
6115 free(trule->act_prm.trk_ctr.table.n);
6116 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006117 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006118 * to pass a list of counters to track and allocate them right here using
6119 * stktable_alloc_data_type().
6120 */
6121 }
6122 }
6123
Emeric Brun32da3c42010-09-23 18:39:19 +02006124 if (curproxy->table.peers.name) {
6125 struct peers *curpeers = peers;
6126
6127 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6128 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6129 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006130 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006131 break;
6132 }
6133 }
6134
6135 if (!curpeers) {
6136 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6137 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006138 free((void *)curproxy->table.peers.name);
6139 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006140 cfgerr++;
6141 }
6142 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006143 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6144 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006145 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006146 cfgerr++;
6147 }
6148 }
6149
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006150 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006151 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006152 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6153 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6154 "proxy", curproxy->id);
6155 cfgerr++;
6156 goto out_uri_auth_compat;
6157 }
6158
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006159 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006160 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006161 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006162 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006163
Willy Tarreau95fa4692010-02-01 13:05:50 +01006164 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6165 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006166
6167 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006168 uri_auth_compat_req[i++] = "realm";
6169 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6170 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006171
Willy Tarreau95fa4692010-02-01 13:05:50 +01006172 uri_auth_compat_req[i++] = "unless";
6173 uri_auth_compat_req[i++] = "{";
6174 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6175 uri_auth_compat_req[i++] = "}";
6176 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006177
Willy Tarreauff011f22011-01-06 17:51:27 +01006178 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6179 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006180 cfgerr++;
6181 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006182 }
6183
Willy Tarreauff011f22011-01-06 17:51:27 +01006184 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006185
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006186 if (curproxy->uri_auth->auth_realm) {
6187 free(curproxy->uri_auth->auth_realm);
6188 curproxy->uri_auth->auth_realm = NULL;
6189 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006190
6191 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006192 }
6193out_uri_auth_compat:
6194
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006195 /* compile the log format */
6196 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006197 if (curproxy->conf.logformat_string != default_http_log_format &&
6198 curproxy->conf.logformat_string != default_tcp_log_format &&
6199 curproxy->conf.logformat_string != clf_http_log_format)
6200 free(curproxy->conf.logformat_string);
6201 curproxy->conf.logformat_string = NULL;
6202 free(curproxy->conf.lfs_file);
6203 curproxy->conf.lfs_file = NULL;
6204 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006205 }
6206
Willy Tarreau62a61232013-04-12 18:13:46 +02006207 if (curproxy->conf.logformat_string) {
6208 curproxy->conf.args.ctx = ARGC_LOG;
6209 curproxy->conf.args.file = curproxy->conf.lfs_file;
6210 curproxy->conf.args.line = curproxy->conf.lfs_line;
6211 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006212 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006213 curproxy->conf.args.file = NULL;
6214 curproxy->conf.args.line = 0;
6215 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006216
Willy Tarreau62a61232013-04-12 18:13:46 +02006217 if (curproxy->conf.uniqueid_format_string) {
6218 curproxy->conf.args.ctx = ARGC_UIF;
6219 curproxy->conf.args.file = curproxy->conf.uif_file;
6220 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006221 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006222 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6223 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006224 curproxy->conf.args.file = NULL;
6225 curproxy->conf.args.line = 0;
6226 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006227
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006228 /* only now we can check if some args remain unresolved.
6229 * This must be done after the users and groups resolution.
6230 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006231 cfgerr += smp_resolve_args(curproxy);
6232 if (!cfgerr)
6233 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006234
Willy Tarreau2738a142006-07-08 17:28:09 +02006235 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006236 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006237 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006238 (!curproxy->timeout.connect ||
6239 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006240 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006241 " | While not properly invalid, you will certainly encounter various problems\n"
6242 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006243 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006244 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006245 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006246 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006247
Willy Tarreau1fa31262007-12-03 00:36:16 +01006248 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6249 * We must still support older configurations, so let's find out whether those
6250 * parameters have been set or must be copied from contimeouts.
6251 */
6252 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006253 if (!curproxy->timeout.tarpit ||
6254 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006255 /* tarpit timeout not set. We search in the following order:
6256 * default.tarpit, curr.connect, default.connect.
6257 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006258 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006259 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006260 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006261 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006262 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006263 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006264 }
6265 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006266 (!curproxy->timeout.queue ||
6267 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006268 /* queue timeout not set. We search in the following order:
6269 * default.queue, curr.connect, default.connect.
6270 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006271 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006272 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006273 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006274 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006275 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006276 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006277 }
6278 }
6279
Willy Tarreau1620ec32011-08-06 17:05:02 +02006280 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006281 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6282 curproxy->check_req = (char *)malloc(curproxy->check_len);
6283 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006284 }
6285
Willy Tarreau193b8c62012-11-22 00:17:38 +01006286 /* ensure that cookie capture length is not too large */
6287 if (curproxy->capture_len >= global.tune.cookie_len) {
6288 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6289 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6290 err_code |= ERR_WARN;
6291 curproxy->capture_len = global.tune.cookie_len - 1;
6292 }
6293
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006294 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006295 if (curproxy->nb_req_cap) {
6296 if (curproxy->mode == PR_MODE_HTTP) {
6297 curproxy->req_cap_pool = create_pool("ptrcap",
6298 curproxy->nb_req_cap * sizeof(char *),
6299 MEM_F_SHARED);
6300 } else {
6301 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6302 proxy_type_str(curproxy), curproxy->id);
6303 err_code |= ERR_WARN;
6304 curproxy->to_log &= ~LW_REQHDR;
6305 curproxy->nb_req_cap = 0;
6306 }
6307 }
6308
6309 if (curproxy->nb_rsp_cap) {
6310 if (curproxy->mode == PR_MODE_HTTP) {
6311 curproxy->rsp_cap_pool = create_pool("ptrcap",
6312 curproxy->nb_rsp_cap * sizeof(char *),
6313 MEM_F_SHARED);
6314 } else {
6315 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6316 proxy_type_str(curproxy), curproxy->id);
6317 err_code |= ERR_WARN;
6318 curproxy->to_log &= ~LW_REQHDR;
6319 curproxy->nb_rsp_cap = 0;
6320 }
6321 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006322
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 /* first, we will invert the servers list order */
6324 newsrv = NULL;
6325 while (curproxy->srv) {
6326 struct server *next;
6327
6328 next = curproxy->srv->next;
6329 curproxy->srv->next = newsrv;
6330 newsrv = curproxy->srv;
6331 if (!next)
6332 break;
6333 curproxy->srv = next;
6334 }
6335
Willy Tarreau17edc812014-01-03 12:14:34 +01006336 /* Check that no server name conflicts. This causes trouble in the stats.
6337 * We only emit a warning for the first conflict affecting each server,
6338 * in order to avoid combinatory explosion if all servers have the same
6339 * name. We do that only for servers which do not have an explicit ID,
6340 * because these IDs were made also for distinguishing them and we don't
6341 * want to annoy people who correctly manage them.
6342 */
6343 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6344 struct server *other_srv;
6345
6346 if (newsrv->puid)
6347 continue;
6348
6349 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6350 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6351 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6352 newsrv->conf.file, newsrv->conf.line,
6353 proxy_type_str(curproxy), curproxy->id,
6354 newsrv->id, other_srv->conf.line);
6355 break;
6356 }
6357 }
6358 }
6359
Willy Tarreaudd701652010-05-25 23:03:02 +02006360 /* assign automatic UIDs to servers which don't have one yet */
6361 next_id = 1;
6362 newsrv = curproxy->srv;
6363 while (newsrv != NULL) {
6364 if (!newsrv->puid) {
6365 /* server ID not set, use automatic numbering with first
6366 * spare entry starting with next_svid.
6367 */
6368 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6369 newsrv->conf.id.key = newsrv->puid = next_id;
6370 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6371 }
6372 next_id++;
6373 newsrv = newsrv->next;
6374 }
6375
Willy Tarreau20697042007-11-15 23:26:18 +01006376 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006377 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378
Willy Tarreau62c3be22012-01-20 13:12:32 +01006379 /*
6380 * If this server supports a maxconn parameter, it needs a dedicated
6381 * tasks to fill the emptied slots when a connection leaves.
6382 * Also, resolve deferred tracking dependency if needed.
6383 */
6384 newsrv = curproxy->srv;
6385 while (newsrv != NULL) {
6386 if (newsrv->minconn > newsrv->maxconn) {
6387 /* Only 'minconn' was specified, or it was higher than or equal
6388 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6389 * this will avoid further useless expensive computations.
6390 */
6391 newsrv->maxconn = newsrv->minconn;
6392 } else if (newsrv->maxconn && !newsrv->minconn) {
6393 /* minconn was not specified, so we set it to maxconn */
6394 newsrv->minconn = newsrv->maxconn;
6395 }
6396
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006397#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006398 if (newsrv->use_ssl || newsrv->check.use_ssl)
6399 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006400#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006401
Willy Tarreau2f075e92013-12-03 11:11:34 +01006402 /* set the check type on the server */
6403 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6404
Willy Tarreau62c3be22012-01-20 13:12:32 +01006405 if (newsrv->trackit) {
6406 struct proxy *px;
6407 struct server *srv;
6408 char *pname, *sname;
6409
6410 pname = newsrv->trackit;
6411 sname = strrchr(pname, '/');
6412
6413 if (sname)
6414 *sname++ = '\0';
6415 else {
6416 sname = pname;
6417 pname = NULL;
6418 }
6419
6420 if (pname) {
6421 px = findproxy(pname, PR_CAP_BE);
6422 if (!px) {
6423 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6424 proxy_type_str(curproxy), curproxy->id,
6425 newsrv->id, pname);
6426 cfgerr++;
6427 goto next_srv;
6428 }
6429 } else
6430 px = curproxy;
6431
6432 srv = findserver(px, sname);
6433 if (!srv) {
6434 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6435 proxy_type_str(curproxy), curproxy->id,
6436 newsrv->id, sname);
6437 cfgerr++;
6438 goto next_srv;
6439 }
6440
Willy Tarreauff5ae352013-12-11 20:36:34 +01006441 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006442 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6443 "tracking as it does not have checks enabled.\n",
6444 proxy_type_str(curproxy), curproxy->id,
6445 newsrv->id, px->id, srv->id);
6446 cfgerr++;
6447 goto next_srv;
6448 }
6449
6450 if (curproxy != px &&
6451 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6452 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6453 "tracking: disable-on-404 option inconsistency.\n",
6454 proxy_type_str(curproxy), curproxy->id,
6455 newsrv->id, px->id, srv->id);
6456 cfgerr++;
6457 goto next_srv;
6458 }
6459
6460 /* if the other server is forced disabled, we have to do the same here */
6461 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006462 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006463 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006464 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006465 }
6466
6467 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006468 newsrv->tracknext = srv->trackers;
6469 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006470
6471 free(newsrv->trackit);
6472 newsrv->trackit = NULL;
6473 }
6474 next_srv:
6475 newsrv = newsrv->next;
6476 }
6477
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006478 /* We have to initialize the server lookup mechanism depending
6479 * on what LB algorithm was choosen.
6480 */
6481
6482 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6483 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6484 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006485 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6486 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6487 init_server_map(curproxy);
6488 } else {
6489 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6490 fwrr_init_server_groups(curproxy);
6491 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006492 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006493
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006494 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006495 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6496 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6497 fwlc_init_server_tree(curproxy);
6498 } else {
6499 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6500 fas_init_server_tree(curproxy);
6501 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006502 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006503
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006504 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006505 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6506 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6507 chash_init_server_tree(curproxy);
6508 } else {
6509 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6510 init_server_map(curproxy);
6511 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006512 break;
6513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006514
6515 if (curproxy->options & PR_O_LOGASAP)
6516 curproxy->to_log &= ~LW_BYTES;
6517
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006518 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006519 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006520 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6521 proxy_type_str(curproxy), curproxy->id);
6522 err_code |= ERR_WARN;
6523 }
6524
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006525 if (curproxy->mode != PR_MODE_HTTP) {
6526 int optnum;
6527
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006528 if (curproxy->uri_auth) {
6529 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6530 proxy_type_str(curproxy), curproxy->id);
6531 err_code |= ERR_WARN;
6532 curproxy->uri_auth = NULL;
6533 }
6534
Willy Tarreau87cf5142011-08-19 22:57:24 +02006535 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006536 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6537 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6538 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006539 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006540 }
6541
6542 if (curproxy->options & PR_O_ORGTO) {
6543 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6544 "originalto", proxy_type_str(curproxy), curproxy->id);
6545 err_code |= ERR_WARN;
6546 curproxy->options &= ~PR_O_ORGTO;
6547 }
6548
6549 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6550 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6551 (curproxy->cap & cfg_opts[optnum].cap) &&
6552 (curproxy->options & cfg_opts[optnum].val)) {
6553 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6554 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6555 err_code |= ERR_WARN;
6556 curproxy->options &= ~cfg_opts[optnum].val;
6557 }
6558 }
6559
6560 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6561 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6562 (curproxy->cap & cfg_opts2[optnum].cap) &&
6563 (curproxy->options2 & cfg_opts2[optnum].val)) {
6564 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6565 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6566 err_code |= ERR_WARN;
6567 curproxy->options2 &= ~cfg_opts2[optnum].val;
6568 }
6569 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006570
Pieter Baauwd551fb52013-05-08 22:49:23 +02006571#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006572 if (curproxy->conn_src.bind_hdr_occ) {
6573 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006574 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006575 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006576 err_code |= ERR_WARN;
6577 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006578#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006579 }
6580
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006582 * ensure that we're not cross-dressing a TCP server into HTTP.
6583 */
6584 newsrv = curproxy->srv;
6585 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006586 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006587 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6588 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006589 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006590 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006591
Willy Tarreau0cec3312011-10-31 13:49:26 +01006592 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6593 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6594 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6595 err_code |= ERR_WARN;
6596 }
6597
Willy Tarreau82ffa392013-08-13 17:19:08 +02006598 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6599 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6600 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6601 err_code |= ERR_WARN;
6602 }
6603
Pieter Baauwd551fb52013-05-08 22:49:23 +02006604#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006605 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6606 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006607 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006608 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006609 err_code |= ERR_WARN;
6610 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006611#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006612 newsrv = newsrv->next;
6613 }
6614
Willy Tarreauc1a21672009-08-16 22:37:44 +02006615 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006616 if (!curproxy->accept)
6617 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006618
Willy Tarreauc1a21672009-08-16 22:37:44 +02006619 if (curproxy->tcp_req.inspect_delay ||
6620 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006621 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006622
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006623 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006624 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006625 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006626 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006627
6628 /* both TCP and HTTP must check switching rules */
6629 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6630 }
6631
6632 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006633 if (curproxy->tcp_req.inspect_delay ||
6634 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6635 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6636
Emeric Brun97679e72010-09-23 17:56:44 +02006637 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6638 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6639
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006640 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006641 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006642 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006643 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006644
6645 /* If the backend does requires RDP cookie persistence, we have to
6646 * enable the corresponding analyser.
6647 */
6648 if (curproxy->options2 & PR_O2_RDPC_PRST)
6649 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6650 }
6651
Emeric Brunc52962f2012-11-15 18:28:02 +01006652#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006653 /* Configure SSL for each bind line.
6654 * Note: if configuration fails at some point, the ->ctx member
6655 * remains NULL so that listeners can later detach.
6656 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006657 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006658 if (!bind_conf->is_ssl) {
6659 if (bind_conf->default_ctx) {
6660 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6661 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6662 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006663 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006664 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006665 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006666 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006667 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006668 cfgerr++;
6669 continue;
6670 }
6671
Emeric Brun4b3091e2012-09-24 15:48:52 +02006672 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006673 Alert("Unable to allocate SSL session cache.\n");
6674 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006675 continue;
6676 }
6677
Emeric Brunfc0421f2012-09-07 17:30:07 +02006678 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006679 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006680 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006681#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006682
Willy Tarreaue6b98942007-10-29 01:09:36 +01006683 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006684 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006685 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006686 if (!listener->luid) {
6687 /* listener ID not set, use automatic numbering with first
6688 * spare entry starting with next_luid.
6689 */
6690 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6691 listener->conf.id.key = listener->luid = next_id;
6692 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006693 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006694 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006695
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006696 /* enable separate counters */
6697 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6698 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006699 if (!listener->name)
6700 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006701 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006702
Willy Tarreaue6b98942007-10-29 01:09:36 +01006703 if (curproxy->options & PR_O_TCP_NOLING)
6704 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006705 if (!listener->maxconn)
6706 listener->maxconn = curproxy->maxconn;
6707 if (!listener->backlog)
6708 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006709 if (!listener->maxaccept)
6710 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6711
6712 /* we want to have an optimal behaviour on single process mode to
6713 * maximize the work at once, but in multi-process we want to keep
6714 * some fairness between processes, so we target half of the max
6715 * number of events to be balanced over all the processes the proxy
6716 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6717 * used to disable the limit.
6718 */
6719 if (listener->maxaccept > 0) {
6720 if (nbproc > 1)
6721 listener->maxaccept = (listener->maxaccept + 1) / 2;
6722 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6723 }
6724
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006725 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006726 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006727 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006728 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006729
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006730 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6731 listener->options |= LI_O_TCP_RULES;
6732
Willy Tarreaude3041d2010-05-31 10:56:17 +02006733 if (curproxy->mon_mask.s_addr)
6734 listener->options |= LI_O_CHK_MONNET;
6735
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006736 /* smart accept mode is automatic in HTTP mode */
6737 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006738 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006739 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6740 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006741 }
6742
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006743 /* Release unused SSL configs */
6744 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6745 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006746 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006747#ifdef USE_OPENSSL
6748 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006749 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006750 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006751 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006752 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006753#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006754 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006755
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006756 /* Check multi-process mode compatibility for the current proxy */
6757 if (global.nbproc > 1) {
6758 int nbproc = 0;
6759 if (curproxy->bind_proc) {
6760 int proc;
6761 for (proc = 0; proc < global.nbproc; proc++) {
6762 if (curproxy->bind_proc & (1 << proc)) {
6763 nbproc++;
6764 }
6765 }
6766 } else {
6767 nbproc = global.nbproc;
6768 }
6769 if (curproxy->table.peers.name) {
6770 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6771 curproxy->id);
6772 cfgerr++;
6773 }
6774 if (nbproc > 1) {
6775 if (curproxy->uri_auth) {
6776 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6777 curproxy->id);
6778 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6779 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6780 curproxy->id);
6781 }
6782 }
6783 if (curproxy->appsession_name) {
6784 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6785 curproxy->id);
6786 }
6787 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6788 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6789 curproxy->id);
6790 }
6791 }
6792 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006793
6794 /* create the task associated with the proxy */
6795 curproxy->task = task_new();
6796 if (curproxy->task) {
6797 curproxy->task->context = curproxy;
6798 curproxy->task->process = manage_proxy;
6799 /* no need to queue, it will be done automatically if some
6800 * listener gets limited.
6801 */
6802 curproxy->task->expire = TICK_ETERNITY;
6803 } else {
6804 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6805 curproxy->id);
6806 cfgerr++;
6807 }
6808
Willy Tarreaubaaee002006-06-26 02:48:02 +02006809 curproxy = curproxy->next;
6810 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006811
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006812 /* Check multi-process mode compatibility */
6813 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006814 if (global.stats_fe && !global.stats_fe->bind_proc) {
6815 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding using 'stats bind-process'.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006816 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006817 }
6818
6819 /* automatically compute fullconn if not set. We must not do it in the
6820 * loop above because cross-references are not yet fully resolved.
6821 */
6822 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6823 /* If <fullconn> is not set, let's set it to 10% of the sum of
6824 * the possible incoming frontend's maxconns.
6825 */
6826 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6827 struct proxy *fe;
6828 int total = 0;
6829
6830 /* sum up the number of maxconns of frontends which
6831 * reference this backend at least once or which are
6832 * the same one ('listen').
6833 */
6834 for (fe = proxy; fe; fe = fe->next) {
6835 struct switching_rule *rule;
6836 struct hdr_exp *exp;
6837 int found = 0;
6838
6839 if (!(fe->cap & PR_CAP_FE))
6840 continue;
6841
6842 if (fe == curproxy) /* we're on a "listen" instance */
6843 found = 1;
6844
6845 if (fe->defbe.be == curproxy) /* "default_backend" */
6846 found = 1;
6847
6848 /* check if a "use_backend" rule matches */
6849 if (!found) {
6850 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006851 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006852 found = 1;
6853 break;
6854 }
6855 }
6856 }
6857
6858 /* check if a "reqsetbe" rule matches */
6859 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6860 if (exp->action == ACT_SETBE &&
6861 (struct proxy *)exp->replace == curproxy) {
6862 found = 1;
6863 break;
6864 }
6865 }
6866
6867 /* now we've checked all possible ways to reference a backend
6868 * from a frontend.
6869 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006870 if (!found)
6871 continue;
6872 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006873 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006874 /* we have the sum of the maxconns in <total>. We only
6875 * keep 10% of that sum to set the default fullconn, with
6876 * a hard minimum of 1 (to avoid a divide by zero).
6877 */
6878 curproxy->fullconn = (total + 9) / 10;
6879 if (!curproxy->fullconn)
6880 curproxy->fullconn = 1;
6881 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006882 }
6883
Willy Tarreau056f5682010-06-06 15:51:11 +02006884 /* initialize stick-tables on backend capable proxies. This must not
6885 * be done earlier because the data size may be discovered while parsing
6886 * other proxies.
6887 */
Godbach9703e662013-12-11 21:11:41 +08006888 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006889 if (curproxy->state == PR_STSTOPPED)
6890 continue;
6891
Godbach9703e662013-12-11 21:11:41 +08006892 if (!stktable_init(&curproxy->table)) {
6893 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6894 cfgerr++;
6895 }
6896 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006897
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006898 /*
6899 * Recount currently required checks.
6900 */
6901
6902 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6903 int optnum;
6904
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006905 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6906 if (curproxy->options & cfg_opts[optnum].val)
6907 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006908
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006909 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6910 if (curproxy->options2 & cfg_opts2[optnum].val)
6911 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006912 }
6913
Willy Tarreau122541c2011-09-07 21:24:49 +02006914 if (peers) {
6915 struct peers *curpeers = peers, **last;
6916 struct peer *p, *pb;
6917
6918 /* Remove all peers sections which don't have a valid listener.
6919 * This can happen when a peers section is never referenced and
6920 * does not contain a local peer.
6921 */
6922 last = &peers;
6923 while (*last) {
6924 curpeers = *last;
6925 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01006926 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02006927 last = &curpeers->next;
6928 continue;
6929 }
6930
6931 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6932 curpeers->id, localpeer);
6933
6934 p = curpeers->remote;
6935 while (p) {
6936 pb = p->next;
6937 free(p->id);
6938 free(p);
6939 p = pb;
6940 }
6941
6942 /* Destroy and unlink this curpeers section.
6943 * Note: curpeers is backed up into *last.
6944 */
6945 free(curpeers->id);
6946 curpeers = curpeers->next;
6947 free(*last);
6948 *last = curpeers;
6949 }
6950 }
6951
Willy Tarreau34eb6712011-10-24 18:15:04 +02006952 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006953 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006954 MEM_F_SHARED);
6955
Willy Tarreaubb925012009-07-23 13:36:36 +02006956 if (cfgerr > 0)
6957 err_code |= ERR_ALERT | ERR_FATAL;
6958 out:
6959 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006960}
6961
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006962/*
6963 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6964 * parsing sessions.
6965 */
6966void cfg_register_keywords(struct cfg_kw_list *kwl)
6967{
6968 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6969}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006970
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006971/*
6972 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6973 */
6974void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6975{
6976 LIST_DEL(&kwl->list);
6977 LIST_INIT(&kwl->list);
6978}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006980/* this function register new section in the haproxy configuration file.
6981 * <section_name> is the name of this new section and <section_parser>
6982 * is the called parser. If two section declaration have the same name,
6983 * only the first declared is used.
6984 */
6985int cfg_register_section(char *section_name,
6986 int (*section_parser)(const char *, int, char **, int))
6987{
6988 struct cfg_section *cs;
6989
6990 cs = calloc(1, sizeof(*cs));
6991 if (!cs) {
6992 Alert("register section '%s': out of memory.\n", section_name);
6993 return 0;
6994 }
6995
6996 cs->section_name = section_name;
6997 cs->section_parser = section_parser;
6998
6999 LIST_ADDQ(&sections, &cs->list);
7000
7001 return 1;
7002}
7003
Willy Tarreaubaaee002006-06-26 02:48:02 +02007004/*
7005 * Local variables:
7006 * c-indent-level: 8
7007 * c-basic-offset: 8
7008 * End:
7009 */