blob: 3af0449e4db51091e0bd7ba6cda4db55245a136a [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
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreaueb0c6142007-05-07 00:53:22 +020053#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010054#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020056#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020058#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020059#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020060#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020061#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020062#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010063#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020064#include <proto/lb_fwlc.h>
65#include <proto/lb_fwrr.h>
66#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020069#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020071#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010072#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010073#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020074#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020075#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010077#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020078#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010080#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#ifdef USE_OPENSSL
83#include <types/ssl_sock.h>
84#include <proto/ssl_sock.h>
85#include <proto/shctx.h>
86#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
Willy Tarreauf3c69202006-07-09 16:42:34 +020088/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
89 * ssl-hello-chk option to ensure that the remote server speaks SSL.
90 *
91 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
92 */
93const char sslv3_client_hello_pkt[] = {
94 "\x16" /* ContentType : 0x16 = Hanshake */
95 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
96 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
97 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
98 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
99 "\x03\x00" /* Hello Version : 0x0300 = v3 */
100 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
101 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
102 "\x00" /* Session ID length : empty (no session ID) */
103 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
104 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
105 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
106 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
107 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
108 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
109 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
110 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
111 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
112 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
113 "\x00\x38" "\x00\x39" "\x00\x3A"
114 "\x01" /* Compression Length : 0x01 = 1 byte for types */
115 "\x00" /* Compression Type : 0x00 = NULL compression */
116};
117
Willy Tarreau3842f002009-06-14 11:39:52 +0200118/* various keyword modifiers */
119enum kw_mod {
120 KWM_STD = 0, /* normal */
121 KWM_NO, /* "no" prefixed before the keyword */
122 KWM_DEF, /* "default" prefixed before the keyword */
123};
124
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100125/* permit to store configuration section */
126struct cfg_section {
127 struct list list;
128 char *section_name;
129 int (*section_parser)(const char *, int, char **, int);
130};
131
132/* Used to chain configuration sections definitions. This list
133 * stores struct cfg_section
134 */
135struct list sections = LIST_HEAD_INIT(sections);
136
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100138struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139 const char *name;
140 unsigned int val;
141 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100142 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144};
145
146/* proxy->options */
147static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
150 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
151 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
152 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
153 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
154 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100156 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
158 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
159 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
160 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
161 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100162#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100164#else
165 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100166#endif
167
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100169};
170
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100171/* proxy->options2 */
172static const struct cfg_opt cfg_opts2[] =
173{
174#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100175 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
177 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100178#else
179 { "splice-request", 0, 0, 0, 0 },
180 { "splice-response", 0, 0, 0, 0 },
181 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100182#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100183 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
184 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
185 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
186 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
187 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
188 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
190 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
191 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400192 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100193 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200194 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200195 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100196 { NULL, 0, 0, 0 }
197};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198
Willy Tarreau6daf3432008-01-22 16:44:08 +0100199static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
201int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100202int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200204/* List head of all known configuration keywords */
205static struct cfg_kw_list cfg_keywords = {
206 .list = LIST_HEAD_INIT(cfg_keywords.list)
207};
208
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209/*
210 * converts <str> to a list of listeners which are dynamically allocated.
211 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
212 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
213 * - <port> is a numerical port from 1 to 65535 ;
214 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
215 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200216 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
217 * not NULL, it must be a valid pointer to either NULL or a freeable area that
218 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200220int 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 +0200221{
222 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 int port, end;
225
226 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100229 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100230 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
232 str = next;
233 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100234 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 *next++ = 0;
236 }
237
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100238 ss2 = str2sa_range(str, &port, &end, err,
239 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
240 if (!ss2)
241 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100244 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200245 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100249 if (!port || !end) {
250 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
251 goto fail;
252 }
253
Emeric Bruned760922010-10-22 17:59:25 +0200254 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200255 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
258
259 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200260 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200261 goto fail;
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100264 else if (ss2->ss_family == AF_UNSPEC) {
265 socklen_t addr_len;
266
267 /* We want to attach to an already bound fd whose number
268 * is in the addr part of ss2 when cast to sockaddr_in.
269 * Note that by definition there is a single listener.
270 * We still have to determine the address family to
271 * register the correct protocol.
272 */
273 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
274 addr_len = sizeof(*ss2);
275 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
276 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
277 goto fail;
278 }
279
280 port = end = get_host_port(ss2);
281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100283 /* OK the address looks correct */
284 ss = *ss2;
285
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 for (; port <= end; port++) {
287 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100288 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200289 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
290 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
291 l->frontend = curproxy;
292 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293
Willy Tarreau40aa0702013-03-10 23:51:38 +0100294 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200296 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100297 l->state = LI_INIT;
298
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100299 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 tcpv4_add_listener(l);
302 }
Emeric Bruned760922010-10-22 17:59:25 +0200303 else if (ss.ss_family == AF_INET6) {
304 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
305 tcpv6_add_listener(l);
306 }
307 else {
Emeric Bruned760922010-10-22 17:59:25 +0200308 uxst_add_listener(l);
309 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200310
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200311 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100312 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313 } /* end for(port) */
314 } /* end while(next) */
315 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 fail:
318 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200319 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320}
321
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200322/* Report a warning if a rule is placed after a 'tcp-request content' rule.
323 * Return 1 if the warning has been emitted, otherwise 0.
324 */
325int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
326{
327 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
328 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
329 file, line, arg);
330 return 1;
331 }
332 return 0;
333}
334
Willy Tarreau61d18892009-03-31 10:49:21 +0200335/* Report a warning if a rule is placed after a 'block' rule.
336 * Return 1 if the warning has been emitted, otherwise 0.
337 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100338int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200339{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200340 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200341 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
342 file, line, arg);
343 return 1;
344 }
345 return 0;
346}
347
Willy Tarreau5002f572014-04-23 01:32:02 +0200348/* Report a warning if a rule is placed after an 'http_request' rule.
349 * Return 1 if the warning has been emitted, otherwise 0.
350 */
351int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
352{
353 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
354 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
355 file, line, arg);
356 return 1;
357 }
358 return 0;
359}
360
Willy Tarreau61d18892009-03-31 10:49:21 +0200361/* Report a warning if a rule is placed after a reqrewrite rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100364int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200365{
366 if (proxy->req_exp) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
374/* Report a warning if a rule is placed after a reqadd rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100379 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
387/* Report a warning if a rule is placed after a redirect rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
392 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
393 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
400/* Report a warning if a rule is placed after a 'use_backend' rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
Willy Tarreauee445d92014-04-23 01:39:04 +0200413/* Report a warning if a rule is placed after a 'use-server' rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
416int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
417{
418 if (!LIST_ISEMPTY(&proxy->server_rules)) {
419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200426/* report a warning if a "tcp request connection" rule is dangerously placed */
427int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
428{
429 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
430 warnif_rule_after_block(proxy, file, line, arg) ||
431 warnif_rule_after_http_req(proxy, file, line, arg) ||
432 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
433 warnif_rule_after_reqadd(proxy, file, line, arg) ||
434 warnif_rule_after_redirect(proxy, file, line, arg) ||
435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a "tcp request content" rule is dangerously placed */
440int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_block(proxy, file, line, arg) ||
443 warnif_rule_after_http_req(proxy, file, line, arg) ||
444 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
445 warnif_rule_after_reqadd(proxy, file, line, arg) ||
446 warnif_rule_after_redirect(proxy, file, line, arg) ||
447 warnif_rule_after_use_backend(proxy, file, line, arg) ||
448 warnif_rule_after_use_server(proxy, file, line, arg);
449}
450
Willy Tarreau61d18892009-03-31 10:49:21 +0200451/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100452int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200453{
Willy Tarreau5002f572014-04-23 01:32:02 +0200454 return warnif_rule_after_http_req(proxy, file, line, arg) ||
455 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
456 warnif_rule_after_reqadd(proxy, file, line, arg) ||
457 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200458 warnif_rule_after_use_backend(proxy, file, line, arg) ||
459 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200460}
461
462/* report a warning if an http-request rule is dangerously placed */
463int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
464{
Willy Tarreau61d18892009-03-31 10:49:21 +0200465 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
466 warnif_rule_after_reqadd(proxy, file, line, arg) ||
467 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200468 warnif_rule_after_use_backend(proxy, file, line, arg) ||
469 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200470}
471
472/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100473int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200474{
475 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
476 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200477 warnif_rule_after_use_backend(proxy, file, line, arg) ||
478 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200479}
480
481/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100482int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200483{
484 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200485 warnif_rule_after_use_backend(proxy, file, line, arg) ||
486 warnif_rule_after_use_server(proxy, file, line, arg);
487}
488
489/* report a warning if a redirect rule is dangerously placed */
490int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
491{
492 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
493 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200494}
495
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100496/* Report it if a request ACL condition uses some keywords that are incompatible
497 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
498 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
499 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100500 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100501static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100502{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100503 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200504 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100505
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100506 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100507 return 0;
508
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100509 acl = acl_cond_conflicts(cond, where);
510 if (acl) {
511 if (acl->name && *acl->name)
512 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
513 file, line, acl->name, sample_ckp_names(where));
514 else
515 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 +0200516 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100517 return ERR_WARN;
518 }
519 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100520 return 0;
521
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100522 if (acl->name && *acl->name)
523 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200524 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100525 else
526 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200527 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100528 return ERR_WARN;
529}
530
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200532 * parse a line in a <global> section. Returns the error code, 0 if OK, or
533 * any combination of :
534 * - ERR_ABORT: must abort ASAP
535 * - ERR_FATAL: we can continue parsing but not start the service
536 * - ERR_WARN: a warning has been emitted
537 * - ERR_ALERT: an alert has been emitted
538 * Only the two first ones can stop processing, the two others are just
539 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200541int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542{
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200544 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545
546 if (!strcmp(args[0], "global")) { /* new section */
547 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200550 else if (!strcmp(args[0], "ca-base")) {
551#ifdef USE_OPENSSL
552 if (global.ca_base != NULL) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.ca_base = strdup(args[1]);
563#else
564 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567#endif
568 }
569 else if (!strcmp(args[0], "crt-base")) {
570#ifdef USE_OPENSSL
571 if (global.crt_base != NULL) {
572 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT;
574 goto out;
575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.crt_base = strdup(args[1]);
582#else
583 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586#endif
587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 else if (!strcmp(args[0], "daemon")) {
589 global.mode |= MODE_DAEMON;
590 }
591 else if (!strcmp(args[0], "debug")) {
592 global.mode |= MODE_DEBUG;
593 }
594 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100595 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200597 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100598 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100601 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100603 else if (!strcmp(args[0], "nosplice")) {
604 global.tune.options &= ~GTUNE_USE_SPLICE;
605 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200606 else if (!strcmp(args[0], "nogetaddrinfo")) {
607 global.tune.options &= ~GTUNE_USE_GAI;
608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 else if (!strcmp(args[0], "quiet")) {
610 global.mode |= MODE_QUIET;
611 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200612 else if (!strcmp(args[0], "tune.maxpollevents")) {
613 if (global.tune.maxpollevents != 0) {
614 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200622 }
623 global.tune.maxpollevents = atol(args[1]);
624 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100625 else if (!strcmp(args[0], "tune.maxaccept")) {
626 if (global.tune.maxaccept != 0) {
627 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT;
629 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100635 }
636 global.tune.maxaccept = atol(args[1]);
637 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200638 else if (!strcmp(args[0], "tune.chksize")) {
639 if (*(args[1]) == 0) {
640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.chksize = atol(args[1]);
645 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200646#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200647 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
648 global.tune.sslprivatecache = 1;
649 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100650 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.sslcachesize = atol(args[1]);
657 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100658 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
659 unsigned int ssllifetime;
660 const char *res;
661
662 if (*(args[1]) == 0) {
663 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
664 err_code |= ERR_ALERT | ERR_FATAL;
665 goto out;
666 }
667
668 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
669 if (res) {
670 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
671 file, linenum, *res, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675
676 global.tune.ssllifetime = ssllifetime;
677 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100678 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
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.ssl_max_record = atol(args[1]);
685 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200686 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
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.ssl_default_dh_param = atol(args[1]);
693 if (global.tune.ssl_default_dh_param < 1024) {
694 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
697 }
698 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200699#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100700 else if (!strcmp(args[0], "tune.buffers.limit")) {
701 if (*(args[1]) == 0) {
702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
703 err_code |= ERR_ALERT | ERR_FATAL;
704 goto out;
705 }
706 global.tune.buf_limit = atol(args[1]);
707 if (global.tune.buf_limit) {
708 if (global.tune.buf_limit < 3)
709 global.tune.buf_limit = 3;
710 if (global.tune.buf_limit <= global.tune.reserved_bufs)
711 global.tune.buf_limit = global.tune.reserved_bufs + 1;
712 }
713 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100714 else if (!strcmp(args[0], "tune.buffers.reserve")) {
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.reserved_bufs = atol(args[1]);
721 if (global.tune.reserved_bufs < 2)
722 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100723 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
724 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100725 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200726 else if (!strcmp(args[0], "tune.bufsize")) {
727 if (*(args[1]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 global.tune.bufsize = atol(args[1]);
733 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
734 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100735 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100736 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200737 }
738 else if (!strcmp(args[0], "tune.maxrewrite")) {
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.maxrewrite = atol(args[1]);
745 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
746 global.tune.maxrewrite = global.tune.bufsize / 2;
747 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100748 else if (!strcmp(args[0], "tune.idletimer")) {
749 unsigned int idle;
750 const char *res;
751
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757
758 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
759 if (res) {
760 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
761 file, linenum, *res, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (idle > 65535) {
767 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 global.tune.idle_timer = idle;
772 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100773 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
774 if (global.tune.client_rcvbuf != 0) {
775 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
776 err_code |= ERR_ALERT;
777 goto out;
778 }
779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
783 }
784 global.tune.client_rcvbuf = atol(args[1]);
785 }
786 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
787 if (global.tune.server_rcvbuf != 0) {
788 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
789 err_code |= ERR_ALERT;
790 goto out;
791 }
792 if (*(args[1]) == 0) {
793 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
796 }
797 global.tune.server_rcvbuf = atol(args[1]);
798 }
799 else if (!strcmp(args[0], "tune.sndbuf.client")) {
800 if (global.tune.client_sndbuf != 0) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT;
803 goto out;
804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.client_sndbuf = atol(args[1]);
811 }
812 else if (!strcmp(args[0], "tune.sndbuf.server")) {
813 if (global.tune.server_sndbuf != 0) {
814 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
815 err_code |= ERR_ALERT;
816 goto out;
817 }
818 if (*(args[1]) == 0) {
819 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
820 err_code |= ERR_ALERT | ERR_FATAL;
821 goto out;
822 }
823 global.tune.server_sndbuf = atol(args[1]);
824 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200825 else if (!strcmp(args[0], "tune.pipesize")) {
826 if (*(args[1]) == 0) {
827 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 global.tune.pipesize = atol(args[1]);
832 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100833 else if (!strcmp(args[0], "tune.http.cookielen")) {
834 if (*(args[1]) == 0) {
835 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT | ERR_FATAL;
837 goto out;
838 }
839 global.tune.cookie_len = atol(args[1]) + 1;
840 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200841 else if (!strcmp(args[0], "tune.http.maxhdr")) {
842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.max_http_hdr = atol(args[1]);
848 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100849 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
850#ifdef USE_ZLIB
851 if (*args[1]) {
852 global.tune.zlibmemlevel = atoi(args[1]);
853 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 } else {
860 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
861 file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865#else
866 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869#endif
870 }
871 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
872#ifdef USE_ZLIB
873 if (*args[1]) {
874 global.tune.zlibwindowsize = atoi(args[1]);
875 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 } else {
882 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
883 file, linenum, args[0]);
884 err_code |= ERR_ALERT | ERR_FATAL;
885 goto out;
886 }
887#else
888 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891#endif
892 }
William Lallemandf3747832012-11-09 12:33:10 +0100893 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
894 if (*args[1]) {
895 global.tune.comp_maxlevel = atoi(args[1]);
896 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
897 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
898 file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 } else {
903 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
904 file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 else if (!strcmp(args[0], "uid")) {
910 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200911 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 }
915 if (*(args[1]) == 0) {
916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 }
920 global.uid = atol(args[1]);
921 }
922 else if (!strcmp(args[0], "gid")) {
923 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200924 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT;
926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 if (*(args[1]) == 0) {
929 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT | ERR_FATAL;
931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 global.gid = atol(args[1]);
934 }
Simon Horman98637e52014-06-20 12:30:16 +0900935 else if (!strcmp(args[0], "external-check")) {
936 global.external_check = 1;
937 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200938 /* user/group name handling */
939 else if (!strcmp(args[0], "user")) {
940 struct passwd *ha_user;
941 if (global.uid != 0) {
942 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT;
944 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200945 }
946 errno = 0;
947 ha_user = getpwnam(args[1]);
948 if (ha_user != NULL) {
949 global.uid = (int)ha_user->pw_uid;
950 }
951 else {
952 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 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200954 }
955 }
956 else if (!strcmp(args[0], "group")) {
957 struct group *ha_group;
958 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200959 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200962 }
963 errno = 0;
964 ha_group = getgrnam(args[1]);
965 if (ha_group != NULL) {
966 global.gid = (int)ha_group->gr_gid;
967 }
968 else {
969 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 +0200970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200971 }
972 }
973 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200979 }
980 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100981 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
982 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
983 file, linenum, args[0], LONGBITS, global.nbproc);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200987 }
988 else if (!strcmp(args[0], "maxconn")) {
989 if (global.maxconn != 0) {
990 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999 global.maxconn = atol(args[1]);
1000#ifdef SYSTEM_MAXCONN
1001 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1002 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);
1003 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001004 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006#endif /* SYSTEM_MAXCONN */
1007 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001008 else if (!strcmp(args[0], "maxsslconn")) {
1009#ifdef USE_OPENSSL
1010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
1014 }
1015 global.maxsslconn = atol(args[1]);
1016#else
Emeric Brun0914df82012-10-02 18:45:42 +02001017 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001020#endif
1021 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001022 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1023#ifdef USE_OPENSSL
1024 if (*(args[1]) == 0) {
1025 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029 free(global.listen_default_ciphers);
1030 global.listen_default_ciphers = strdup(args[1]);
1031#else
1032 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035#endif
1036 }
1037 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1038#ifdef USE_OPENSSL
1039 if (*(args[1]) == 0) {
1040 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044 free(global.connect_default_ciphers);
1045 global.connect_default_ciphers = strdup(args[1]);
1046#else
1047 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050#endif
1051 }
Emeric Brun850efd52014-01-29 12:24:34 +01001052 else if (!strcmp(args[0], "ssl-server-verify")) {
1053 if (*(args[1]) == 0) {
1054 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 if (strcmp(args[1],"none") == 0)
1059 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1060 else if (strcmp(args[1],"required") == 0)
1061 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1062 else {
1063 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
1066 }
1067 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001068 else if (!strcmp(args[0], "maxconnrate")) {
1069 if (global.cps_lim != 0) {
1070 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT;
1072 goto out;
1073 }
1074 if (*(args[1]) == 0) {
1075 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079 global.cps_lim = atol(args[1]);
1080 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001081 else if (!strcmp(args[0], "maxsessrate")) {
1082 if (global.sps_lim != 0) {
1083 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1084 err_code |= ERR_ALERT;
1085 goto out;
1086 }
1087 if (*(args[1]) == 0) {
1088 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto out;
1091 }
1092 global.sps_lim = atol(args[1]);
1093 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001094 else if (!strcmp(args[0], "maxsslrate")) {
1095 if (global.ssl_lim != 0) {
1096 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT;
1098 goto out;
1099 }
1100 if (*(args[1]) == 0) {
1101 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
1104 }
1105 global.ssl_lim = atol(args[1]);
1106 }
William Lallemandd85f9172012-11-09 17:05:39 +01001107 else if (!strcmp(args[0], "maxcomprate")) {
1108 if (*(args[1]) == 0) {
1109 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113 global.comp_rate_lim = atoi(args[1]) * 1024;
1114 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001115 else if (!strcmp(args[0], "maxpipes")) {
1116 if (global.maxpipes != 0) {
1117 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT;
1119 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001120 }
1121 if (*(args[1]) == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001125 }
1126 global.maxpipes = atol(args[1]);
1127 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001128 else if (!strcmp(args[0], "maxzlibmem")) {
1129 if (*(args[1]) == 0) {
1130 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
1133 }
William Lallemande3a7d992012-11-20 11:25:20 +01001134 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001135 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001136 else if (!strcmp(args[0], "maxcompcpuusage")) {
1137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
1141 }
1142 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001143 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001144 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
1148}
1149
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 else if (!strcmp(args[0], "ulimit-n")) {
1151 if (global.rlimit_nofile != 0) {
1152 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001153 err_code |= ERR_ALERT;
1154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 }
1156 if (*(args[1]) == 0) {
1157 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 }
1161 global.rlimit_nofile = atol(args[1]);
1162 }
1163 else if (!strcmp(args[0], "chroot")) {
1164 if (global.chroot != NULL) {
1165 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT;
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 if (*(args[1]) == 0) {
1170 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 global.chroot = strdup(args[1]);
1175 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001176 else if (!strcmp(args[0], "description")) {
1177 int i, len=0;
1178 char *d;
1179
1180 if (!*args[1]) {
1181 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1182 file, linenum, args[0]);
1183 err_code |= ERR_ALERT | ERR_FATAL;
1184 goto out;
1185 }
1186
Willy Tarreau348acfe2014-04-14 15:00:39 +02001187 for (i = 1; *args[i]; i++)
1188 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001189
1190 if (global.desc)
1191 free(global.desc);
1192
1193 global.desc = d = (char *)calloc(1, len);
1194
Willy Tarreau348acfe2014-04-14 15:00:39 +02001195 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1196 for (i = 2; *args[i]; i++)
1197 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001198 }
1199 else if (!strcmp(args[0], "node")) {
1200 int i;
1201 char c;
1202
1203 for (i=0; args[1][i]; i++) {
1204 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001205 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1206 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001207 break;
1208 }
1209
1210 if (!i || args[1][i]) {
1211 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1212 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1213 file, linenum, args[0]);
1214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
1216 }
1217
1218 if (global.node)
1219 free(global.node);
1220
1221 global.node = strdup(args[1]);
1222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 else if (!strcmp(args[0], "pidfile")) {
1224 if (global.pidfile != NULL) {
1225 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001226 err_code |= ERR_ALERT;
1227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 }
1229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 }
1234 global.pidfile = strdup(args[1]);
1235 }
Emeric Bruned760922010-10-22 17:59:25 +02001236 else if (!strcmp(args[0], "unix-bind")) {
1237 int cur_arg = 1;
1238 while (*(args[cur_arg])) {
1239 if (!strcmp(args[cur_arg], "prefix")) {
1240 if (global.unix_bind.prefix != NULL) {
1241 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1242 err_code |= ERR_ALERT;
1243 cur_arg += 2;
1244 continue;
1245 }
1246
1247 if (*(args[cur_arg+1]) == 0) {
1248 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1253 cur_arg += 2;
1254 continue;
1255 }
1256
1257 if (!strcmp(args[cur_arg], "mode")) {
1258
1259 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (!strcmp(args[cur_arg], "uid")) {
1265
1266 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1267 cur_arg += 2;
1268 continue;
1269 }
1270
1271 if (!strcmp(args[cur_arg], "gid")) {
1272
1273 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1274 cur_arg += 2;
1275 continue;
1276 }
1277
1278 if (!strcmp(args[cur_arg], "user")) {
1279 struct passwd *user;
1280
1281 user = getpwnam(args[cur_arg + 1]);
1282 if (!user) {
1283 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1284 file, linenum, args[0], args[cur_arg + 1 ]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288
1289 global.unix_bind.ux.uid = user->pw_uid;
1290 cur_arg += 2;
1291 continue;
1292 }
1293
1294 if (!strcmp(args[cur_arg], "group")) {
1295 struct group *group;
1296
1297 group = getgrnam(args[cur_arg + 1]);
1298 if (!group) {
1299 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1300 file, linenum, args[0], args[cur_arg + 1 ]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
1304
1305 global.unix_bind.ux.gid = group->gr_gid;
1306 cur_arg += 2;
1307 continue;
1308 }
1309
Willy Tarreaub48f9582011-09-05 01:17:06 +02001310 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001311 file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 }
William Lallemand0f99e342011-10-12 17:50:54 +02001316 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1317 /* delete previous herited or defined syslog servers */
1318 struct logsrv *back;
1319 struct logsrv *tmp;
1320
1321 if (*(args[1]) != 0) {
1322 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326
1327 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1328 LIST_DEL(&tmp->list);
1329 free(tmp);
1330 }
1331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001333 struct sockaddr_storage *sk;
1334 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001335 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001336 int arg = 0;
1337 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001338
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 if (*(args[1]) == 0 || *(args[2]) == 0) {
1340 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
William Lallemand0f99e342011-10-12 17:50:54 +02001344
1345 logsrv = calloc(1, sizeof(struct logsrv));
1346
Willy Tarreau18324f52014-06-27 18:10:07 +02001347 /* just after the address, a length may be specified */
1348 if (strcmp(args[arg+2], "len") == 0) {
1349 len = atoi(args[arg+3]);
1350 if (len < 80 || len > 65535) {
1351 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1352 file, linenum, args[arg+3]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356 logsrv->maxlen = len;
1357
1358 /* skip these two args */
1359 arg += 2;
1360 }
1361 else
1362 logsrv->maxlen = MAX_SYSLOG_LEN;
1363
1364 if (logsrv->maxlen > global.max_syslog_len) {
1365 global.max_syslog_len = logsrv->maxlen;
1366 logline = realloc(logline, global.max_syslog_len + 1);
1367 }
1368
1369 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001370 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001371 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001372 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001373 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 }
1375
William Lallemand0f99e342011-10-12 17:50:54 +02001376 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001377 if (*(args[arg+3])) {
1378 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001379 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001380 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001381 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001382 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
1384 }
1385
William Lallemand0f99e342011-10-12 17:50:54 +02001386 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001387 if (*(args[arg+4])) {
1388 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001389 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001390 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001392 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001393 }
1394 }
1395
Willy Tarreau902636f2013-03-10 19:44:48 +01001396 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001397 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001398 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001399 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001400 free(logsrv);
1401 goto out;
1402 }
1403 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001404
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001405 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001406 if (port1 != port2) {
1407 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1408 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001409 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001410 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001411 goto out;
1412 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001413
William Lallemand0f99e342011-10-12 17:50:54 +02001414 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001415 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001416 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
William Lallemand0f99e342011-10-12 17:50:54 +02001419 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001420 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001421 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1422 char *name;
1423 int len;
1424
1425 if (global.log_send_hostname != NULL) {
1426 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1427 err_code |= ERR_ALERT;
1428 goto out;
1429 }
1430
1431 if (*(args[1]))
1432 name = args[1];
1433 else
1434 name = hostname;
1435
1436 len = strlen(name);
1437
1438 /* We'll add a space after the name to respect the log format */
1439 free(global.log_send_hostname);
1440 global.log_send_hostname = malloc(len + 2);
1441 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1442 }
Kevinm48936af2010-12-22 16:08:21 +00001443 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449 free(global.log_tag);
1450 global.log_tag = strdup(args[1]);
1451 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001452 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1453 if (global.spread_checks != 0) {
1454 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001455 err_code |= ERR_ALERT;
1456 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001457 }
1458 if (*(args[1]) == 0) {
1459 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001462 }
1463 global.spread_checks = atol(args[1]);
1464 if (global.spread_checks < 0 || global.spread_checks > 50) {
1465 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001469 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1470 const char *err;
1471 unsigned int val;
1472
1473
1474 if (*(args[1]) == 0) {
1475 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1476 err_code |= ERR_ALERT | ERR_FATAL;
1477 goto out;
1478 }
1479
1480 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1481 if (err) {
1482 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1483 err_code |= ERR_ALERT | ERR_FATAL;
1484 }
1485 global.max_spread_checks = val;
1486 if (global.max_spread_checks < 0) {
1487 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1488 err_code |= ERR_ALERT | ERR_FATAL;
1489 }
1490 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001491 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1492#ifdef USE_CPU_AFFINITY
1493 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001494 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001495 unsigned long cpus = 0;
1496
1497 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001498 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001499 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001500 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001501 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001502 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001503 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001504 proc = atol(args[1]);
1505 if (proc >= 1 && proc <= LONGBITS)
1506 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001507 }
1508
1509 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001510 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1511 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto out;
1514 }
1515
1516 cur_arg = 2;
1517 while (*args[cur_arg]) {
1518 unsigned int low, high;
1519
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001520 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001521 char *dash = strchr(args[cur_arg], '-');
1522
1523 low = high = str2uic(args[cur_arg]);
1524 if (dash)
1525 high = str2uic(dash + 1);
1526
1527 if (high < low) {
1528 unsigned int swap = low;
1529 low = high;
1530 high = swap;
1531 }
1532
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001533 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001534 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001535 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539
1540 while (low <= high)
1541 cpus |= 1UL << low++;
1542 }
1543 else {
1544 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1545 file, linenum, args[0], args[cur_arg]);
1546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto out;
1548 }
1549 cur_arg++;
1550 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001551 for (i = 0; i < LONGBITS; i++)
1552 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001553 global.cpu_map[i] = cpus;
1554#else
1555 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
1558#endif
1559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001561 struct cfg_kw_list *kwl;
1562 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001563 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001564
1565 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1566 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1567 if (kwl->kw[index].section != CFG_GLOBAL)
1568 continue;
1569 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001570 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001571 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001572 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001574 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001575 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001576 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001577 err_code |= ERR_WARN;
1578 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001579 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001580 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001581 }
1582 }
1583 }
1584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001588
Willy Tarreau058e9072009-07-20 09:30:05 +02001589 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001590 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001591 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592}
1593
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001594void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001596 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 defproxy.mode = PR_MODE_TCP;
1598 defproxy.state = PR_STNEW;
1599 defproxy.maxconn = cfg_maxpconn;
1600 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001601
Simon Horman66183002013-02-23 10:16:43 +09001602 defproxy.defsrv.check.inter = DEF_CHKINTR;
1603 defproxy.defsrv.check.fastinter = 0;
1604 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001605 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1606 defproxy.defsrv.agent.fastinter = 0;
1607 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001608 defproxy.defsrv.check.rise = DEF_RISETIME;
1609 defproxy.defsrv.check.fall = DEF_FALLTIME;
1610 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1611 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001612 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001613 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001614 defproxy.defsrv.maxqueue = 0;
1615 defproxy.defsrv.minconn = 0;
1616 defproxy.defsrv.maxconn = 0;
1617 defproxy.defsrv.slowstart = 0;
1618 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1619 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1620 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621}
1622
Willy Tarreauade5ec42010-01-28 19:33:49 +01001623
Willy Tarreau63af98d2014-05-18 08:11:41 +02001624/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1625 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1626 * ERR_FATAL in case of error.
1627 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001628static int create_cond_regex_rule(const char *file, int line,
1629 struct proxy *px, int dir, int action, int flags,
1630 const char *cmd, const char *reg, const char *repl,
1631 const char **cond_start)
1632{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001633 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001634 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001635 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001636 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001637 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001638 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001639 int cs;
1640 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001641
1642 if (px == &defproxy) {
1643 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001644 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001645 goto err;
1646 }
1647
1648 if (*reg == 0) {
1649 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001650 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001651 goto err;
1652 }
1653
1654 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001655 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656
Willy Tarreau5321c422010-01-28 20:35:13 +01001657 if (cond_start &&
1658 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001659 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1660 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1661 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001662 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001663 goto err;
1664 }
1665 }
1666 else if (cond_start && **cond_start) {
1667 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1668 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001669 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001670 goto err;
1671 }
1672
Willy Tarreau63af98d2014-05-18 08:11:41 +02001673 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001674 (dir == SMP_OPT_DIR_REQ) ?
1675 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1676 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1677 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001678
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001679 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001680 if (!preg) {
1681 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001682 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001683 goto err;
1684 }
1685
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001686 cs = !(flags & REG_ICASE);
1687 cap = !(flags & REG_NOSUB);
1688 error = NULL;
1689 if (!regex_comp(reg, preg, cs, cap, &error)) {
1690 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1691 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001692 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001693 goto err;
1694 }
1695
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001696 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001697 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001698 if (repl && err) {
1699 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1700 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001701 ret_code |= ERR_ALERT | ERR_FATAL;
1702 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001703 }
1704
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001705 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001706 ret_code |= ERR_WARN;
1707
1708 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001709
Willy Tarreau63af98d2014-05-18 08:11:41 +02001710 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001711 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001712 err:
1713 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001714 free(errmsg);
1715 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001716}
1717
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001719 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001720 * Returns the error code, 0 if OK, or any combination of :
1721 * - ERR_ABORT: must abort ASAP
1722 * - ERR_FATAL: we can continue parsing but not start the service
1723 * - ERR_WARN: a warning has been emitted
1724 * - ERR_ALERT: an alert has been emitted
1725 * Only the two first ones can stop processing, the two others are just
1726 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001728int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1729{
1730 static struct peers *curpeers = NULL;
1731 struct peer *newpeer = NULL;
1732 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001733 struct bind_conf *bind_conf;
1734 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001735 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001736 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001737
1738 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001739 if (!*args[1]) {
1740 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001741 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001742 goto out;
1743 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001744
1745 err = invalid_char(args[1]);
1746 if (err) {
1747 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1748 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001749 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001750 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001751 }
1752
1753 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1754 /*
1755 * If there are two proxies with the same name only following
1756 * combinations are allowed:
1757 */
1758 if (strcmp(curpeers->id, args[1]) == 0) {
1759 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1760 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1761 err_code |= ERR_WARN;
1762 }
1763 }
1764
1765 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1766 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1767 err_code |= ERR_ALERT | ERR_ABORT;
1768 goto out;
1769 }
1770
1771 curpeers->next = peers;
1772 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001773 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001774 curpeers->conf.line = linenum;
1775 curpeers->last_change = now.tv_sec;
1776 curpeers->id = strdup(args[1]);
1777 }
1778 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001779 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001780 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001781 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001782
1783 if (!*args[2]) {
1784 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1785 file, linenum, args[0]);
1786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
1788 }
1789
1790 err = invalid_char(args[1]);
1791 if (err) {
1792 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1793 file, linenum, *err, args[1]);
1794 err_code |= ERR_ALERT | ERR_FATAL;
1795 goto out;
1796 }
1797
1798 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1799 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1800 err_code |= ERR_ALERT | ERR_ABORT;
1801 goto out;
1802 }
1803
1804 /* the peers are linked backwards first */
1805 curpeers->count++;
1806 newpeer->next = curpeers->remote;
1807 curpeers->remote = newpeer;
1808 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001809 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001810 newpeer->conf.line = linenum;
1811
1812 newpeer->last_change = now.tv_sec;
1813 newpeer->id = strdup(args[1]);
1814
Willy Tarreau902636f2013-03-10 19:44:48 +01001815 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001816 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001817 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001820 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001821
1822 proto = protocol_by_family(sk->ss_family);
1823 if (!proto || !proto->connect) {
1824 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1825 file, linenum, args[0], args[1]);
1826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
1828 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001829
1830 if (port1 != port2) {
1831 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1832 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836
Willy Tarreau2aa38802013-02-20 19:20:59 +01001837 if (!port1) {
1838 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1839 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001843
Emeric Brun32da3c42010-09-23 18:39:19 +02001844 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001845 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001846 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001847 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001848
Emeric Brun32da3c42010-09-23 18:39:19 +02001849 if (strcmp(newpeer->id, localpeer) == 0) {
1850 /* Current is local peer, it define a frontend */
1851 newpeer->local = 1;
1852
1853 if (!curpeers->peers_fe) {
1854 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1855 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1856 err_code |= ERR_ALERT | ERR_ABORT;
1857 goto out;
1858 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001859
Willy Tarreau237250c2011-07-29 01:49:03 +02001860 init_new_proxy(curpeers->peers_fe);
1861 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001862
1863 curpeers->peers_fe->last_change = now.tv_sec;
1864 curpeers->peers_fe->id = strdup(args[1]);
1865 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001866 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001867 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1868 curpeers->peers_fe->timeout.connect = 5000;
1869 curpeers->peers_fe->accept = peer_accept;
1870 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001871 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1872 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001873
1874 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1875
Willy Tarreau902636f2013-03-10 19:44:48 +01001876 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1877 if (errmsg && *errmsg) {
1878 indent_msg(&errmsg, 2);
1879 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001880 }
1881 else
1882 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1883 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001884 err_code |= ERR_FATAL;
1885 goto out;
1886 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001887
1888 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001889 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001890 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1891 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1892 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1893 l->accept = session_accept;
1894 l->handler = process_session;
1895 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1896 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1897 global.maxsock += l->maxconn;
1898 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001899 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001900 else {
1901 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1902 file, linenum, args[0], args[1],
1903 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1904 err_code |= ERR_FATAL;
1905 goto out;
1906 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001907 }
1908 } /* neither "peer" nor "peers" */
1909 else if (*args[0] != 0) {
1910 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
1913 }
1914
1915out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001916 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001917 return err_code;
1918}
1919
Simon Horman0d16a402015-01-30 11:22:58 +09001920
1921/*
1922 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1923 * Returns the error code, 0 if OK, or any combination of :
1924 * - ERR_ABORT: must abort ASAP
1925 * - ERR_FATAL: we can continue parsing but not start the service
1926 * - ERR_WARN: a warning has been emitted
1927 * - ERR_ALERT: an alert has been emitted
1928 * Only the two first ones can stop processing, the two others are just
1929 * indicators.
1930 */
1931int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1932{
1933 static struct mailers *curmailers = NULL;
1934 struct mailer *newmailer = NULL;
1935 const char *err;
1936 int err_code = 0;
1937 char *errmsg = NULL;
1938
1939 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1940 if (!*args[1]) {
1941 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1942 err_code |= ERR_ALERT | ERR_ABORT;
1943 goto out;
1944 }
1945
1946 err = invalid_char(args[1]);
1947 if (err) {
1948 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1949 file, linenum, *err, args[0], args[1]);
1950 err_code |= ERR_ALERT | ERR_ABORT;
1951 goto out;
1952 }
1953
1954 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1955 /*
1956 * If there are two proxies with the same name only following
1957 * combinations are allowed:
1958 */
1959 if (strcmp(curmailers->id, args[1]) == 0) {
1960 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1961 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1962 err_code |= ERR_WARN;
1963 }
1964 }
1965
1966 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1967 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1968 err_code |= ERR_ALERT | ERR_ABORT;
1969 goto out;
1970 }
1971
1972 curmailers->next = mailers;
1973 mailers = curmailers;
1974 curmailers->conf.file = strdup(file);
1975 curmailers->conf.line = linenum;
1976 curmailers->id = strdup(args[1]);
1977 }
1978 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1979 struct sockaddr_storage *sk;
1980 int port1, port2;
1981 struct protocol *proto;
1982
1983 if (!*args[2]) {
1984 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1985 file, linenum, args[0]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
1989
1990 err = invalid_char(args[1]);
1991 if (err) {
1992 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1993 file, linenum, *err, args[1]);
1994 err_code |= ERR_ALERT | ERR_FATAL;
1995 goto out;
1996 }
1997
1998 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
1999 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2000 err_code |= ERR_ALERT | ERR_ABORT;
2001 goto out;
2002 }
2003
2004 /* the mailers are linked backwards first */
2005 curmailers->count++;
2006 newmailer->next = curmailers->mailer_list;
2007 curmailers->mailer_list = newmailer;
2008 newmailer->mailers = curmailers;
2009 newmailer->conf.file = strdup(file);
2010 newmailer->conf.line = linenum;
2011
2012 newmailer->id = strdup(args[1]);
2013
2014 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2015 if (!sk) {
2016 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
2019 }
2020
2021 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002022 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2023 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002024 file, linenum, args[0], args[1]);
2025 err_code |= ERR_ALERT | ERR_FATAL;
2026 goto out;
2027 }
2028
2029 if (port1 != port2) {
2030 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2031 file, linenum, args[0], args[1], args[2]);
2032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
2034 }
2035
2036 if (!port1) {
2037 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2038 file, linenum, args[0], args[1], args[2]);
2039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
2041 }
2042
2043 newmailer->addr = *sk;
2044 newmailer->proto = proto;
2045 newmailer->xprt = &raw_sock;
2046 newmailer->sock_init_arg = NULL;
2047 } /* neither "mailer" nor "mailers" */
2048 else if (*args[0] != 0) {
2049 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
2052 }
2053
2054out:
2055 free(errmsg);
2056 return err_code;
2057}
2058
Simon Horman9dc49962015-01-30 11:22:59 +09002059static void free_email_alert(struct proxy *p)
2060{
2061 free(p->email_alert.mailers.name);
2062 p->email_alert.mailers.name = NULL;
2063 free(p->email_alert.from);
2064 p->email_alert.from = NULL;
2065 free(p->email_alert.to);
2066 p->email_alert.to = NULL;
2067 free(p->email_alert.myhostname);
2068 p->email_alert.myhostname = NULL;
2069}
2070
Willy Tarreau3842f002009-06-14 11:39:52 +02002071int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072{
2073 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002074 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002075 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002076 int rc;
2077 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002078 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002079 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002080 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002081 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002082 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083
Willy Tarreau977b8e42006-12-29 14:19:17 +01002084 if (!strcmp(args[0], "listen"))
2085 rc = PR_CAP_LISTEN;
2086 else if (!strcmp(args[0], "frontend"))
2087 rc = PR_CAP_FE | PR_CAP_RS;
2088 else if (!strcmp(args[0], "backend"))
2089 rc = PR_CAP_BE | PR_CAP_RS;
2090 else if (!strcmp(args[0], "ruleset"))
2091 rc = PR_CAP_RS;
2092 else
2093 rc = PR_CAP_NONE;
2094
2095 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002096 struct ebpt_node *node;
2097
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 if (!*args[1]) {
2099 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2100 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_ABORT;
2103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002105
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002106 err = invalid_char(args[1]);
2107 if (err) {
2108 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2109 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002111 }
2112
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002113 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2114 curproxy = container_of(node, struct proxy, conf.by_name);
2115
2116 if (strcmp(curproxy->id, args[1]) != 0)
2117 break;
2118
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002119 /*
2120 * If there are two proxies with the same name only following
2121 * combinations are allowed:
2122 *
2123 * listen backend frontend ruleset
2124 * listen - - - -
2125 * backend - - OK -
2126 * frontend - OK - -
2127 * ruleset - - - -
2128 */
2129
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002130 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2131 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002132 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2133 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2134 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002136 }
2137 }
2138
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2140 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_ABORT;
2142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002144
Willy Tarreau97cb7802010-01-03 20:23:58 +01002145 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 curproxy->next = proxy;
2147 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002148 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2149 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002150 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002153 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002154
2155 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002156 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002157 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002158
Willy Tarreau4348fad2012-09-20 16:48:07 +02002159 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2160
Willy Tarreau902636f2013-03-10 19:44:48 +01002161 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2162 if (errmsg && *errmsg) {
2163 indent_msg(&errmsg, 2);
2164 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002165 }
2166 else
2167 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2168 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002169 err_code |= ERR_FATAL;
2170 goto out;
2171 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002172
Willy Tarreau4348fad2012-09-20 16:48:07 +02002173 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002174 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
2177
2178 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002179 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002180 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002181
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002184 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002185 curproxy->no_options = defproxy.no_options;
2186 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002187 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002188 curproxy->except_net = defproxy.except_net;
2189 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002190 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002191 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002193 if (defproxy.fwdfor_hdr_len) {
2194 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2195 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2196 }
2197
Willy Tarreaub86db342009-11-30 11:50:16 +01002198 if (defproxy.orgto_hdr_len) {
2199 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2200 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2201 }
2202
Mark Lamourinec2247f02012-01-04 13:02:01 -05002203 if (defproxy.server_id_hdr_len) {
2204 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2205 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2206 }
2207
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 if (curproxy->cap & PR_CAP_FE) {
2209 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002210 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002211 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212
2213 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002214 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2215 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002216
2217 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219
Willy Tarreau977b8e42006-12-29 14:19:17 +01002220 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002221 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002222 curproxy->fullconn = defproxy.fullconn;
2223 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002224 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002226 if (defproxy.check_req) {
2227 curproxy->check_req = calloc(1, defproxy.check_len);
2228 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2229 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002230 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002232 if (defproxy.expect_str) {
2233 curproxy->expect_str = strdup(defproxy.expect_str);
2234 if (defproxy.expect_regex) {
2235 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002236 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2237 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002238 }
2239 }
2240
Willy Tarreau67402132012-05-31 20:40:20 +02002241 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242 if (defproxy.cookie_name)
2243 curproxy->cookie_name = strdup(defproxy.cookie_name);
2244 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002245 if (defproxy.cookie_domain)
2246 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002247
Willy Tarreau31936852010-10-06 16:59:56 +02002248 if (defproxy.cookie_maxidle)
2249 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2250
2251 if (defproxy.cookie_maxlife)
2252 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2253
Emeric Brun647caf12009-06-30 17:57:00 +02002254 if (defproxy.rdp_cookie_name)
2255 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2256 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2257
Willy Tarreau01732802007-11-01 22:48:15 +01002258 if (defproxy.url_param_name)
2259 curproxy->url_param_name = strdup(defproxy.url_param_name);
2260 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002261
Benoitaffb4812009-03-25 13:02:10 +01002262 if (defproxy.hh_name)
2263 curproxy->hh_name = strdup(defproxy.hh_name);
2264 curproxy->hh_len = defproxy.hh_len;
2265 curproxy->hh_match_domain = defproxy.hh_match_domain;
2266
Willy Tarreauef9a3602012-12-08 22:29:20 +01002267 if (defproxy.conn_src.iface_name)
2268 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2269 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002270 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002271#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002272 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002273#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002276 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277 if (defproxy.capture_name)
2278 curproxy->capture_name = strdup(defproxy.capture_name);
2279 curproxy->capture_namelen = defproxy.capture_namelen;
2280 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282
Willy Tarreau977b8e42006-12-29 14:19:17 +01002283 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002284 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002285 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002286 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002287 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002288 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002289 curproxy->mon_net = defproxy.mon_net;
2290 curproxy->mon_mask = defproxy.mon_mask;
2291 if (defproxy.monitor_uri)
2292 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2293 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002294 if (defproxy.defbe.name)
2295 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002296
2297 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002298 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2299 if (curproxy->conf.logformat_string &&
2300 curproxy->conf.logformat_string != default_http_log_format &&
2301 curproxy->conf.logformat_string != default_tcp_log_format &&
2302 curproxy->conf.logformat_string != clf_http_log_format)
2303 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2304
2305 if (defproxy.conf.lfs_file) {
2306 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2307 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2308 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002309 }
2310
2311 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002312 curproxy->timeout.connect = defproxy.timeout.connect;
2313 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002314 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002315 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002316 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002317 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002318 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002319 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002320 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002321 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002322 }
2323
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002325 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002326
2327 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002328 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002329 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002330 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002331 LIST_INIT(&node->list);
2332 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2333 }
2334
Willy Tarreau62a61232013-04-12 18:13:46 +02002335 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2336 if (curproxy->conf.uniqueid_format_string)
2337 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2338
Willy Tarreau094af4e2015-01-07 15:03:42 +01002339 if (defproxy.log_tag)
2340 curproxy->log_tag = strdup(defproxy.log_tag);
2341
Willy Tarreau62a61232013-04-12 18:13:46 +02002342 if (defproxy.conf.uif_file) {
2343 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2344 curproxy->conf.uif_line = defproxy.conf.uif_line;
2345 }
William Lallemanda73203e2012-03-12 12:48:57 +01002346
2347 /* copy default header unique id */
2348 if (defproxy.header_unique_id)
2349 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2350
William Lallemand82fe75c2012-10-23 10:25:10 +02002351 /* default compression options */
2352 if (defproxy.comp != NULL) {
2353 curproxy->comp = calloc(1, sizeof(struct comp));
2354 curproxy->comp->algos = defproxy.comp->algos;
2355 curproxy->comp->types = defproxy.comp->types;
2356 }
2357
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002359 curproxy->conf.used_listener_id = EB_ROOT;
2360 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002361
Simon Horman98637e52014-06-20 12:30:16 +09002362 if (defproxy.check_path)
2363 curproxy->check_path = strdup(defproxy.check_path);
2364 if (defproxy.check_command)
2365 curproxy->check_command = strdup(defproxy.check_command);
2366
Simon Horman9dc49962015-01-30 11:22:59 +09002367 if (defproxy.email_alert.mailers.name)
2368 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2369 if (defproxy.email_alert.from)
2370 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2371 if (defproxy.email_alert.to)
2372 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2373 if (defproxy.email_alert.myhostname)
2374 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
2375
Willy Tarreau93893792009-07-23 13:19:11 +02002376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }
2378 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2379 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002380 /* FIXME-20070101: we should do this too at the end of the
2381 * config parsing to free all default values.
2382 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002383 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002384 free(defproxy.check_command);
2385 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002387 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002388 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002389 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002390 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002391 free(defproxy.capture_name);
2392 free(defproxy.monitor_uri);
2393 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002394 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002395 free(defproxy.fwdfor_hdr_name);
2396 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002397 free(defproxy.orgto_hdr_name);
2398 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002399 free(defproxy.server_id_hdr_name);
2400 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002401 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002402 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002403 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002404 free(defproxy.expect_regex);
2405 defproxy.expect_regex = NULL;
2406 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002407
Willy Tarreau62a61232013-04-12 18:13:46 +02002408 if (defproxy.conf.logformat_string != default_http_log_format &&
2409 defproxy.conf.logformat_string != default_tcp_log_format &&
2410 defproxy.conf.logformat_string != clf_http_log_format)
2411 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002412
Willy Tarreau62a61232013-04-12 18:13:46 +02002413 free(defproxy.conf.uniqueid_format_string);
2414 free(defproxy.conf.lfs_file);
2415 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002416 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002417 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002418
Willy Tarreaua534fea2008-08-03 12:19:50 +02002419 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002420 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002421
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 /* we cannot free uri_auth because it might already be used */
2423 init_default_instance();
2424 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002425 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2426 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002427 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
2430 else if (curproxy == NULL) {
2431 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002435
2436 /* update the current file and line being parsed */
2437 curproxy->conf.args.file = curproxy->conf.file;
2438 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002439
2440 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002441 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2442 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2443 if (err_code & ERR_FATAL)
2444 goto out;
2445 }
2446 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002447 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002448 int cur_arg;
2449
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 if (curproxy == &defproxy) {
2451 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002455 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457
Willy Tarreau24709282013-03-10 21:32:12 +01002458 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002459 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002464
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002465 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002466
2467 /* use default settings for unix sockets */
2468 bind_conf->ux.uid = global.unix_bind.ux.uid;
2469 bind_conf->ux.gid = global.unix_bind.ux.gid;
2470 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002471
2472 /* NOTE: the following line might create several listeners if there
2473 * are comma-separated IPs or port ranges. So all further processing
2474 * will have to be applied to all listeners created after last_listen.
2475 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002476 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2477 if (errmsg && *errmsg) {
2478 indent_msg(&errmsg, 2);
2479 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002480 }
2481 else
2482 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2483 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
2486 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002487
Willy Tarreau4348fad2012-09-20 16:48:07 +02002488 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2489 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002490 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002491 }
2492
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002493 cur_arg = 2;
2494 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002495 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002496 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002497 char *err;
2498
Willy Tarreau26982662012-09-12 23:17:10 +02002499 kw = bind_find_kw(args[cur_arg]);
2500 if (kw) {
2501 char *err = NULL;
2502 int code;
2503
2504 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002505 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2506 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002507 cur_arg += 1 + kw->skip ;
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511
Willy Tarreau4348fad2012-09-20 16:48:07 +02002512 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002513 err_code |= code;
2514
2515 if (code) {
2516 if (err && *err) {
2517 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002518 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002519 }
2520 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002521 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2522 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002523 if (code & ERR_FATAL) {
2524 free(err);
2525 cur_arg += 1 + kw->skip;
2526 goto out;
2527 }
2528 }
2529 free(err);
2530 cur_arg += 1 + kw->skip;
2531 continue;
2532 }
2533
Willy Tarreau8638f482012-09-18 18:01:17 +02002534 err = NULL;
2535 if (!bind_dumped) {
2536 bind_dump_kws(&err);
2537 indent_msg(&err, 4);
2538 bind_dumped = 1;
2539 }
2540
2541 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2542 file, linenum, args[0], args[1], args[cur_arg],
2543 err ? " Registered keywords :" : "", err ? err : "");
2544 free(err);
2545
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002548 }
Willy Tarreau93893792009-07-23 13:19:11 +02002549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 }
2551 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002552 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2554 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002558 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002560
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 /* flush useless bits */
2562 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002565 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002566 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568
Willy Tarreau1c47f852006-07-09 08:22:27 +02002569 if (!*args[1]) {
2570 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002574 }
2575
Willy Tarreaua534fea2008-08-03 12:19:50 +02002576 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002577 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002578 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002579 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002580 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2581
Willy Tarreau93893792009-07-23 13:19:11 +02002582 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2585 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2586 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2587 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2588 else {
2589 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
2593 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002594 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002595 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002596
2597 if (curproxy == &defproxy) {
2598 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2599 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002602 }
2603
2604 if (!*args[1]) {
2605 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2606 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002609 }
2610
2611 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002612 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002613
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002614 if (curproxy->uuid <= 0) {
2615 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002616 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002619 }
2620
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002621 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2622 if (node) {
2623 struct proxy *target = container_of(node, struct proxy, conf.id);
2624 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2625 file, linenum, proxy_type_str(curproxy), curproxy->id,
2626 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002631 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002632 else if (!strcmp(args[0], "description")) {
2633 int i, len=0;
2634 char *d;
2635
Cyril Bonté99ed3272010-01-24 23:29:44 +01002636 if (curproxy == &defproxy) {
2637 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2638 file, linenum, args[0]);
2639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
2641 }
2642
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002643 if (!*args[1]) {
2644 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2645 file, linenum, args[0]);
2646 return -1;
2647 }
2648
Willy Tarreau348acfe2014-04-14 15:00:39 +02002649 for (i = 1; *args[i]; i++)
2650 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002651
2652 d = (char *)calloc(1, len);
2653 curproxy->desc = d;
2654
Willy Tarreau348acfe2014-04-14 15:00:39 +02002655 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2656 for (i = 2; *args[i]; i++)
2657 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002658
2659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2661 curproxy->state = PR_STSTOPPED;
2662 }
2663 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2664 curproxy->state = PR_STNEW;
2665 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002666 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2667 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002668 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002669
2670 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002671 unsigned int low, high;
2672
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002673 if (strcmp(args[cur_arg], "all") == 0) {
2674 set = 0;
2675 break;
2676 }
2677 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002678 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002679 }
2680 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002681 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002682 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002683 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002684 char *dash = strchr(args[cur_arg], '-');
2685
2686 low = high = str2uic(args[cur_arg]);
2687 if (dash)
2688 high = str2uic(dash + 1);
2689
2690 if (high < low) {
2691 unsigned int swap = low;
2692 low = high;
2693 high = swap;
2694 }
2695
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002696 if (low < 1 || high > LONGBITS) {
2697 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2698 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002701 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002702 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002703 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002704 }
2705 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002706 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2707 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002710 }
2711 cur_arg++;
2712 }
2713 curproxy->bind_proc = set;
2714 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002715 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002716 if (curproxy == &defproxy) {
2717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002720 }
2721
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002722 err = invalid_char(args[1]);
2723 if (err) {
2724 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2725 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002727 }
2728
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002729 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002730 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2731 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002734 }
2735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2737 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738
Willy Tarreau977b8e42006-12-29 14:19:17 +01002739 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 if (*(args[1]) == 0) {
2743 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2744 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002748
Willy Tarreau67402132012-05-31 20:40:20 +02002749 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002750 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002751 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002752 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 curproxy->cookie_name = strdup(args[1]);
2754 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002755
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 cur_arg = 2;
2757 while (*(args[cur_arg])) {
2758 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002759 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
2761 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002762 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002765 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 }
2767 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002768 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 }
2770 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002771 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002773 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002774 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002777 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002779 else if (!strcmp(args[cur_arg], "httponly")) {
2780 curproxy->ck_opts |= PR_CK_HTTPONLY;
2781 }
2782 else if (!strcmp(args[cur_arg], "secure")) {
2783 curproxy->ck_opts |= PR_CK_SECURE;
2784 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002785 else if (!strcmp(args[cur_arg], "domain")) {
2786 if (!*args[cur_arg + 1]) {
2787 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2788 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002791 }
2792
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002793 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002794 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002795 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2796 " dots nor does not start with a dot."
2797 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002798 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002799 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002800 }
2801
2802 err = invalid_domainchar(args[cur_arg + 1]);
2803 if (err) {
2804 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2805 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002808 }
2809
Willy Tarreau68a897b2009-12-03 23:28:34 +01002810 if (!curproxy->cookie_domain) {
2811 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2812 } else {
2813 /* one domain was already specified, add another one by
2814 * building the string which will be returned along with
2815 * the cookie.
2816 */
2817 char *new_ptr;
2818 int new_len = strlen(curproxy->cookie_domain) +
2819 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2820 new_ptr = malloc(new_len);
2821 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2822 free(curproxy->cookie_domain);
2823 curproxy->cookie_domain = new_ptr;
2824 }
Willy Tarreau31936852010-10-06 16:59:56 +02002825 cur_arg++;
2826 }
2827 else if (!strcmp(args[cur_arg], "maxidle")) {
2828 unsigned int maxidle;
2829 const char *res;
2830
2831 if (!*args[cur_arg + 1]) {
2832 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2833 file, linenum, args[cur_arg]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837
2838 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2839 if (res) {
2840 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2841 file, linenum, *res, args[cur_arg]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
2845 curproxy->cookie_maxidle = maxidle;
2846 cur_arg++;
2847 }
2848 else if (!strcmp(args[cur_arg], "maxlife")) {
2849 unsigned int maxlife;
2850 const char *res;
2851
2852 if (!*args[cur_arg + 1]) {
2853 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2854 file, linenum, args[cur_arg]);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858
2859 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2860 if (res) {
2861 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2862 file, linenum, *res, args[cur_arg]);
2863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
2865 }
2866 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002867 cur_arg++;
2868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002870 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 +02002871 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 }
2875 cur_arg++;
2876 }
Willy Tarreau67402132012-05-31 20:40:20 +02002877 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2879 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 }
2882
Willy Tarreau67402132012-05-31 20:40:20 +02002883 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2885 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002888
Willy Tarreau67402132012-05-31 20:40:20 +02002889 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002890 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2891 file, linenum);
2892 err_code |= ERR_ALERT | ERR_FATAL;
2893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002895 else if (!strcmp(args[0], "email-alert")) {
2896 if (*(args[1]) == 0) {
2897 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2898 file, linenum, args[0]);
2899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
2901 }
2902
2903 if (!strcmp(args[1], "from")) {
2904 if (*(args[1]) == 0) {
2905 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2906 file, linenum, args[1]);
2907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
2909 }
2910 free(curproxy->email_alert.from);
2911 curproxy->email_alert.from = strdup(args[2]);
2912 }
2913 else if (!strcmp(args[1], "mailers")) {
2914 if (*(args[1]) == 0) {
2915 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2916 file, linenum, args[1]);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
2920 free(curproxy->email_alert.mailers.name);
2921 curproxy->email_alert.mailers.name = strdup(args[2]);
2922 }
2923 else if (!strcmp(args[1], "myhostname")) {
2924 if (*(args[1]) == 0) {
2925 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2926 file, linenum, args[1]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930 free(curproxy->email_alert.myhostname);
2931 curproxy->email_alert.myhostname = strdup(args[2]);
2932 }
2933 else if (!strcmp(args[1], "to")) {
2934 if (*(args[1]) == 0) {
2935 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2936 file, linenum, args[1]);
2937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
2939 }
2940 free(curproxy->email_alert.to);
2941 curproxy->email_alert.to = strdup(args[2]);
2942 }
2943 else {
2944 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2945 file, linenum, args[1]);
2946 err_code |= ERR_ALERT | ERR_FATAL;
2947 goto out;
2948 }
2949 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002950 else if (!strcmp(args[0], "external-check")) {
2951 if (*(args[1]) == 0) {
2952 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2953 file, linenum, args[0]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957
2958 if (!strcmp(args[1], "command")) {
2959 if (*(args[1]) == 0) {
2960 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2961 file, linenum, args[1]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965 free(curproxy->check_command);
2966 curproxy->check_command = strdup(args[2]);
2967 }
2968 else if (!strcmp(args[1], "path")) {
2969 if (*(args[1]) == 0) {
2970 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2971 file, linenum, args[1]);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975 free(curproxy->check_path);
2976 curproxy->check_path = strdup(args[2]);
2977 }
2978 else {
2979 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2980 file, linenum, args[1]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
2984 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002985 else if (!strcmp(args[0], "persist")) { /* persist */
2986 if (*(args[1]) == 0) {
2987 Alert("parsing [%s:%d] : missing persist method.\n",
2988 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002991 }
2992
2993 if (!strncmp(args[1], "rdp-cookie", 10)) {
2994 curproxy->options2 |= PR_O2_RDPC_PRST;
2995
Emeric Brunb982a3d2010-01-04 15:45:53 +01002996 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002997 const char *beg, *end;
2998
2999 beg = args[1] + 11;
3000 end = strchr(beg, ')');
3001
3002 if (!end || end == beg) {
3003 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3004 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003007 }
3008
3009 free(curproxy->rdp_cookie_name);
3010 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3011 curproxy->rdp_cookie_len = end-beg;
3012 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003013 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003014 free(curproxy->rdp_cookie_name);
3015 curproxy->rdp_cookie_name = strdup("msts");
3016 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3017 }
3018 else { /* syntax */
3019 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3020 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003023 }
3024 }
3025 else {
3026 Alert("parsing [%s:%d] : unknown persist method.\n",
3027 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003030 }
3031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003033 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003035 if (curproxy == &defproxy) {
3036 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
3039 }
3040
Willy Tarreau977b8e42006-12-29 14:19:17 +01003041 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003043
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003045 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
3050 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003051 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 curproxy->appsession_name = strdup(args[1]);
3053 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3054 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003055 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3056 if (err) {
3057 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3058 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003061 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003062 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003063
Willy Tarreau51041c72007-09-09 21:56:53 +02003064 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3065 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_ALERT | ERR_ABORT;
3067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003069
3070 cur_arg = 6;
3071 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003072 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3073 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003074 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003075 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003076 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003077 } else if (!strcmp(args[cur_arg], "prefix")) {
3078 curproxy->options2 |= PR_O2_AS_PFX;
3079 } else if (!strcmp(args[cur_arg], "mode")) {
3080 if (!*args[cur_arg + 1]) {
3081 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3082 file, linenum, args[0], args[cur_arg]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086
3087 cur_arg++;
3088 if (!strcmp(args[cur_arg], "query-string")) {
3089 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3090 curproxy->options2 |= PR_O2_AS_M_QS;
3091 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3092 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3093 curproxy->options2 |= PR_O2_AS_M_PP;
3094 } else {
3095 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
3099 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003100 cur_arg++;
3101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 } /* Url App Session */
3103 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003104 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003106
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003108 if (curproxy == &defproxy) {
3109 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 if (*(args[4]) == 0) {
3115 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3116 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003120 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 curproxy->capture_name = strdup(args[2]);
3122 curproxy->capture_namelen = strlen(curproxy->capture_name);
3123 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 curproxy->to_log |= LW_COOKIE;
3125 }
3126 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3127 struct cap_hdr *hdr;
3128
3129 if (curproxy == &defproxy) {
3130 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 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 }
3134
3135 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3136 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3137 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 }
3141
3142 hdr = calloc(sizeof(struct cap_hdr), 1);
3143 hdr->next = curproxy->req_cap;
3144 hdr->name = strdup(args[3]);
3145 hdr->namelen = strlen(args[3]);
3146 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003147 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 hdr->index = curproxy->nb_req_cap++;
3149 curproxy->req_cap = hdr;
3150 curproxy->to_log |= LW_REQHDR;
3151 }
3152 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3153 struct cap_hdr *hdr;
3154
3155 if (curproxy == &defproxy) {
3156 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 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 }
3160
3161 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3162 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3163 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
3167 hdr = calloc(sizeof(struct cap_hdr), 1);
3168 hdr->next = curproxy->rsp_cap;
3169 hdr->name = strdup(args[3]);
3170 hdr->namelen = strlen(args[3]);
3171 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003172 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 hdr->index = curproxy->nb_rsp_cap++;
3174 curproxy->rsp_cap = hdr;
3175 curproxy->to_log |= LW_RSPHDR;
3176 }
3177 else {
3178 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3179 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 }
3183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003185 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003187
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 if (*(args[1]) == 0) {
3189 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3190 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
3194 curproxy->conn_retries = atol(args[1]);
3195 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003196 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003197 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003198
3199 if (curproxy == &defproxy) {
3200 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
3203 }
3204
Willy Tarreau20b0de52012-12-24 15:45:22 +01003205 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3206 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3207 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3208 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003209 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003210 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3211 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 +01003212 file, linenum, args[0]);
3213 err_code |= ERR_WARN;
3214 }
3215
Willy Tarreauff011f22011-01-06 17:51:27 +01003216 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003217
Willy Tarreauff011f22011-01-06 17:51:27 +01003218 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003219 err_code |= ERR_ALERT | ERR_ABORT;
3220 goto out;
3221 }
3222
Willy Tarreau5002f572014-04-23 01:32:02 +02003223 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003224 err_code |= warnif_cond_conflicts(rule->cond,
3225 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3226 file, linenum);
3227
Willy Tarreauff011f22011-01-06 17:51:27 +01003228 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003229 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003230 else if (!strcmp(args[0], "http-response")) { /* response access control */
3231 struct http_res_rule *rule;
3232
3233 if (curproxy == &defproxy) {
3234 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
3238
3239 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3240 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3241 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3242 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3243 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3244 file, linenum, args[0]);
3245 err_code |= ERR_WARN;
3246 }
3247
3248 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3249
3250 if (!rule) {
3251 err_code |= ERR_ALERT | ERR_ABORT;
3252 goto out;
3253 }
3254
3255 err_code |= warnif_cond_conflicts(rule->cond,
3256 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3257 file, linenum);
3258
3259 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3260 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003261 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3262 /* set the header name and length into the proxy structure */
3263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3264 err_code |= ERR_WARN;
3265
3266 if (!*args[1]) {
3267 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3268 file, linenum, args[0]);
3269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
3271 }
3272
3273 /* set the desired header name */
3274 free(curproxy->server_id_hdr_name);
3275 curproxy->server_id_hdr_name = strdup(args[1]);
3276 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3277 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003278 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003279 struct http_req_rule *rule;
3280
Willy Tarreaub099aca2008-10-12 17:26:37 +02003281 if (curproxy == &defproxy) {
3282 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003285 }
3286
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003287 /* emulate "block" using "http-request block". Since these rules are supposed to
3288 * be processed before all http-request rules, we put them into their own list
3289 * and will insert them at the end.
3290 */
3291 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3292 if (!rule) {
3293 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003294 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003295 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003296 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3297 err_code |= warnif_cond_conflicts(rule->cond,
3298 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3299 file, linenum);
3300 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003301
3302 if (!already_warned(WARN_BLOCK_DEPRECATED))
3303 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of 'http-request deny' which uses the exact same syntax. The rules are translated but support might disappear in a future version.\n", file, linenum, args[0]);
3304
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003305 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003306 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003307 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003308
Cyril Bonté99ed3272010-01-24 23:29:44 +01003309 if (curproxy == &defproxy) {
3310 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
3313 }
3314
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003315 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003316 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3317 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003320 }
3321
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003322 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003323 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003324 err_code |= warnif_cond_conflicts(rule->cond,
3325 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3326 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003327 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003328 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003329 struct switching_rule *rule;
3330
Willy Tarreaub099aca2008-10-12 17:26:37 +02003331 if (curproxy == &defproxy) {
3332 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003335 }
3336
Willy Tarreau55ea7572007-06-17 19:56:27 +02003337 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003339
3340 if (*(args[1]) == 0) {
3341 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003344 }
3345
Willy Tarreauf51658d2014-04-23 01:21:56 +02003346 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3347 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3348 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3349 file, linenum, errmsg);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003353
Willy Tarreauf51658d2014-04-23 01:21:56 +02003354 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003355 }
3356
3357 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3358 rule->cond = cond;
3359 rule->be.name = strdup(args[1]);
3360 LIST_INIT(&rule->list);
3361 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3362 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003363 else if (strcmp(args[0], "use-server") == 0) {
3364 struct server_rule *rule;
3365
3366 if (curproxy == &defproxy) {
3367 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371
3372 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3373 err_code |= ERR_WARN;
3374
3375 if (*(args[1]) == 0) {
3376 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380
3381 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3382 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3383 file, linenum, args[0]);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
3387
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003388 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3389 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3390 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003395 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003396
3397 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3398 rule->cond = cond;
3399 rule->srv.name = strdup(args[1]);
3400 LIST_INIT(&rule->list);
3401 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3402 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3403 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003404 else if ((!strcmp(args[0], "force-persist")) ||
3405 (!strcmp(args[0], "ignore-persist"))) {
3406 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003407
3408 if (curproxy == &defproxy) {
3409 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
3412 }
3413
3414 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3415 err_code |= ERR_WARN;
3416
Willy Tarreauef6494c2010-01-28 17:12:36 +01003417 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003418 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3419 file, linenum, args[0]);
3420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
3422 }
3423
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003424 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3425 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3426 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003431 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3432 * where force-persist is applied.
3433 */
3434 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003435
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003436 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003437 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003438 if (!strcmp(args[0], "force-persist")) {
3439 rule->type = PERSIST_TYPE_FORCE;
3440 } else {
3441 rule->type = PERSIST_TYPE_IGNORE;
3442 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003443 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003444 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003445 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003446 else if (!strcmp(args[0], "stick-table")) {
3447 int myidx = 1;
3448
Emeric Brun32da3c42010-09-23 18:39:19 +02003449 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003450 curproxy->table.type = (unsigned int)-1;
3451 while (*args[myidx]) {
3452 const char *err;
3453
3454 if (strcmp(args[myidx], "size") == 0) {
3455 myidx++;
3456 if (!*(args[myidx])) {
3457 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3458 file, linenum, args[myidx-1]);
3459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
3462 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3463 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3464 file, linenum, *err, args[myidx-1]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003468 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003469 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003470 else if (strcmp(args[myidx], "peers") == 0) {
3471 myidx++;
Godbach50523162013-12-11 19:48:57 +08003472 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003473 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3474 file, linenum, args[myidx-1]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Godbach50523162013-12-11 19:48:57 +08003477 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003478 curproxy->table.peers.name = strdup(args[myidx++]);
3479 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003480 else if (strcmp(args[myidx], "expire") == 0) {
3481 myidx++;
3482 if (!*(args[myidx])) {
3483 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3484 file, linenum, args[myidx-1]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3489 if (err) {
3490 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3491 file, linenum, *err, args[myidx-1]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
3495 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003496 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003497 }
3498 else if (strcmp(args[myidx], "nopurge") == 0) {
3499 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003500 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003501 }
3502 else if (strcmp(args[myidx], "type") == 0) {
3503 myidx++;
3504 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3505 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3506 file, linenum, args[myidx]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003510 /* myidx already points to next arg */
3511 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003512 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003513 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003514 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003515
3516 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003517 nw = args[myidx];
3518 while (*nw) {
3519 /* the "store" keyword supports a comma-separated list */
3520 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003521 sa = NULL; /* store arg */
3522 while (*nw && *nw != ',') {
3523 if (*nw == '(') {
3524 *nw = 0;
3525 sa = ++nw;
3526 while (*nw != ')') {
3527 if (!*nw) {
3528 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3529 file, linenum, args[0], cw);
3530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
3532 }
3533 nw++;
3534 }
3535 *nw = '\0';
3536 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003537 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003538 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003539 if (*nw)
3540 *nw++ = '\0';
3541 type = stktable_get_data_type(cw);
3542 if (type < 0) {
3543 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3544 file, linenum, args[0], cw);
3545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
3547 }
Willy Tarreauac782882010-06-20 10:41:54 +02003548
3549 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3550 switch (err) {
3551 case PE_NONE: break;
3552 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003553 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3554 file, linenum, args[0], cw);
3555 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003556 break;
3557
3558 case PE_ARG_MISSING:
3559 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3560 file, linenum, args[0], cw);
3561 err_code |= ERR_ALERT | ERR_FATAL;
3562 goto out;
3563
3564 case PE_ARG_NOT_USED:
3565 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3566 file, linenum, args[0], cw);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569
3570 default:
3571 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3572 file, linenum, args[0], cw);
3573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003575 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003576 }
3577 myidx++;
3578 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003579 else {
3580 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3581 file, linenum, args[myidx]);
3582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003584 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003585 }
3586
3587 if (!curproxy->table.size) {
3588 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3589 file, linenum);
3590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
3592 }
3593
3594 if (curproxy->table.type == (unsigned int)-1) {
3595 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3596 file, linenum);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
3599 }
3600 }
3601 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003602 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003603 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003604 int myidx = 0;
3605 const char *name = NULL;
3606 int flags;
3607
3608 if (curproxy == &defproxy) {
3609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
3612 }
3613
3614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3615 err_code |= ERR_WARN;
3616 goto out;
3617 }
3618
3619 myidx++;
3620 if ((strcmp(args[myidx], "store") == 0) ||
3621 (strcmp(args[myidx], "store-request") == 0)) {
3622 myidx++;
3623 flags = STK_IS_STORE;
3624 }
3625 else if (strcmp(args[myidx], "store-response") == 0) {
3626 myidx++;
3627 flags = STK_IS_STORE | STK_ON_RSP;
3628 }
3629 else if (strcmp(args[myidx], "match") == 0) {
3630 myidx++;
3631 flags = STK_IS_MATCH;
3632 }
3633 else if (strcmp(args[myidx], "on") == 0) {
3634 myidx++;
3635 flags = STK_IS_MATCH | STK_IS_STORE;
3636 }
3637 else {
3638 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
3641 }
3642
3643 if (*(args[myidx]) == 0) {
3644 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
3647 }
3648
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003649 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003650 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003651 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003652 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656
3657 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003658 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3659 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3660 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003661 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003662 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003663 goto out;
3664 }
3665 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003666 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3667 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3668 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003669 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003670 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003671 goto out;
3672 }
3673 }
3674
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003675 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003676 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003677
Emeric Brunb982a3d2010-01-04 15:45:53 +01003678 if (strcmp(args[myidx], "table") == 0) {
3679 myidx++;
3680 name = args[myidx++];
3681 }
3682
Willy Tarreauef6494c2010-01-28 17:12:36 +01003683 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003684 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3685 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3686 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003687 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003688 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003689 goto out;
3690 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003691 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003692 else if (*(args[myidx])) {
3693 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3694 file, linenum, args[0], args[myidx]);
3695 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003696 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003697 goto out;
3698 }
Emeric Brun97679e72010-09-23 17:56:44 +02003699 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003700 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003701 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003702 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003703
Emeric Brunb982a3d2010-01-04 15:45:53 +01003704 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3705 rule->cond = cond;
3706 rule->expr = expr;
3707 rule->flags = flags;
3708 rule->table.name = name ? strdup(name) : NULL;
3709 LIST_INIT(&rule->list);
3710 if (flags & STK_ON_RSP)
3711 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3712 else
3713 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 else if (!strcmp(args[0], "stats")) {
3716 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3717 curproxy->uri_auth = NULL; /* we must detach from the default config */
3718
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003719 if (!*args[1]) {
3720 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003721 } else if (!strcmp(args[1], "admin")) {
3722 struct stats_admin_rule *rule;
3723
3724 if (curproxy == &defproxy) {
3725 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
3729
3730 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3731 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3732 err_code |= ERR_ALERT | ERR_ABORT;
3733 goto out;
3734 }
3735
3736 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3737 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3738 file, linenum, args[0], args[1]);
3739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
3741 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003742 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3743 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3744 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
3747 }
3748
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003749 err_code |= warnif_cond_conflicts(cond,
3750 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3751 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003752
3753 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3754 rule->cond = cond;
3755 LIST_INIT(&rule->list);
3756 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 } else if (!strcmp(args[1], "uri")) {
3758 if (*(args[2]) == 0) {
3759 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3763 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_ALERT | ERR_ABORT;
3765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003766 }
3767 } else if (!strcmp(args[1], "realm")) {
3768 if (*(args[2]) == 0) {
3769 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3773 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_ABORT;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003777 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003778 unsigned interval;
3779
3780 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3781 if (err) {
3782 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3783 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003786 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_ABORT;
3789 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003790 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003791 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003792 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003793
3794 if (curproxy == &defproxy) {
3795 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799
3800 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3801 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3802 err_code |= ERR_ALERT | ERR_ABORT;
3803 goto out;
3804 }
3805
Willy Tarreauff011f22011-01-06 17:51:27 +01003806 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3807 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003808 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3809 file, linenum, args[0]);
3810 err_code |= ERR_WARN;
3811 }
3812
Willy Tarreauff011f22011-01-06 17:51:27 +01003813 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003814
Willy Tarreauff011f22011-01-06 17:51:27 +01003815 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003816 err_code |= ERR_ALERT | ERR_ABORT;
3817 goto out;
3818 }
3819
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003820 err_code |= warnif_cond_conflicts(rule->cond,
3821 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3822 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003823 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003824
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 } else if (!strcmp(args[1], "auth")) {
3826 if (*(args[2]) == 0) {
3827 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3831 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_ABORT;
3833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 }
3835 } else if (!strcmp(args[1], "scope")) {
3836 if (*(args[2]) == 0) {
3837 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3841 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_ABORT;
3843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
3845 } else if (!strcmp(args[1], "enable")) {
3846 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3847 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_ABORT;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003851 } else if (!strcmp(args[1], "hide-version")) {
3852 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3853 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_ABORT;
3855 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003856 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003857 } else if (!strcmp(args[1], "show-legends")) {
3858 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3859 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3860 err_code |= ERR_ALERT | ERR_ABORT;
3861 goto out;
3862 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003863 } else if (!strcmp(args[1], "show-node")) {
3864
3865 if (*args[2]) {
3866 int i;
3867 char c;
3868
3869 for (i=0; args[2][i]; i++) {
3870 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003871 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3872 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003873 break;
3874 }
3875
3876 if (!i || args[2][i]) {
3877 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3878 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3879 file, linenum, args[0], args[1]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 }
3884
3885 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3886 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3887 err_code |= ERR_ALERT | ERR_ABORT;
3888 goto out;
3889 }
3890 } else if (!strcmp(args[1], "show-desc")) {
3891 char *desc = NULL;
3892
3893 if (*args[2]) {
3894 int i, len=0;
3895 char *d;
3896
Willy Tarreau348acfe2014-04-14 15:00:39 +02003897 for (i = 2; *args[i]; i++)
3898 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003899
3900 desc = d = (char *)calloc(1, len);
3901
Willy Tarreau348acfe2014-04-14 15:00:39 +02003902 d += snprintf(d, desc + len - d, "%s", args[2]);
3903 for (i = 3; *args[i]; i++)
3904 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003905 }
3906
3907 if (!*args[2] && !global.desc)
3908 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3909 file, linenum, args[1]);
3910 else {
3911 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3912 free(desc);
3913 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3914 err_code |= ERR_ALERT | ERR_ABORT;
3915 goto out;
3916 }
3917 free(desc);
3918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003920stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003921 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 +01003922 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 }
3926 }
3927 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003928 int optnum;
3929
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003930 if (*(args[1]) == '\0') {
3931 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3932 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003936
3937 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3938 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003939 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3940 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3941 file, linenum, cfg_opts[optnum].name);
3942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
3944 }
Willy Tarreau93893792009-07-23 13:19:11 +02003945 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3946 err_code |= ERR_WARN;
3947 goto out;
3948 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003949
Willy Tarreau3842f002009-06-14 11:39:52 +02003950 curproxy->no_options &= ~cfg_opts[optnum].val;
3951 curproxy->options &= ~cfg_opts[optnum].val;
3952
3953 switch (kwm) {
3954 case KWM_STD:
3955 curproxy->options |= cfg_opts[optnum].val;
3956 break;
3957 case KWM_NO:
3958 curproxy->no_options |= cfg_opts[optnum].val;
3959 break;
3960 case KWM_DEF: /* already cleared */
3961 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003962 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003963
Willy Tarreau93893792009-07-23 13:19:11 +02003964 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003965 }
3966 }
3967
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003968 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3969 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003970 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3971 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3972 file, linenum, cfg_opts2[optnum].name);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
Willy Tarreau93893792009-07-23 13:19:11 +02003976 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3977 err_code |= ERR_WARN;
3978 goto out;
3979 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003980
Willy Tarreau3842f002009-06-14 11:39:52 +02003981 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3982 curproxy->options2 &= ~cfg_opts2[optnum].val;
3983
3984 switch (kwm) {
3985 case KWM_STD:
3986 curproxy->options2 |= cfg_opts2[optnum].val;
3987 break;
3988 case KWM_NO:
3989 curproxy->no_options2 |= cfg_opts2[optnum].val;
3990 break;
3991 case KWM_DEF: /* already cleared */
3992 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003993 }
Willy Tarreau93893792009-07-23 13:19:11 +02003994 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003995 }
3996 }
3997
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003998 /* HTTP options override each other. They can be cancelled using
3999 * "no option xxx" which only switches to default mode if the mode
4000 * was this one (useful for cancelling options set in defaults
4001 * sections).
4002 */
4003 if (strcmp(args[1], "httpclose") == 0) {
4004 if (kwm == KWM_STD) {
4005 curproxy->options &= ~PR_O_HTTP_MODE;
4006 curproxy->options |= PR_O_HTTP_PCL;
4007 goto out;
4008 }
4009 else if (kwm == KWM_NO) {
4010 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4011 curproxy->options &= ~PR_O_HTTP_MODE;
4012 goto out;
4013 }
4014 }
4015 else if (strcmp(args[1], "forceclose") == 0) {
4016 if (kwm == KWM_STD) {
4017 curproxy->options &= ~PR_O_HTTP_MODE;
4018 curproxy->options |= PR_O_HTTP_FCL;
4019 goto out;
4020 }
4021 else if (kwm == KWM_NO) {
4022 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4023 curproxy->options &= ~PR_O_HTTP_MODE;
4024 goto out;
4025 }
4026 }
4027 else if (strcmp(args[1], "http-server-close") == 0) {
4028 if (kwm == KWM_STD) {
4029 curproxy->options &= ~PR_O_HTTP_MODE;
4030 curproxy->options |= PR_O_HTTP_SCL;
4031 goto out;
4032 }
4033 else if (kwm == KWM_NO) {
4034 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4035 curproxy->options &= ~PR_O_HTTP_MODE;
4036 goto out;
4037 }
4038 }
4039 else if (strcmp(args[1], "http-keep-alive") == 0) {
4040 if (kwm == KWM_STD) {
4041 curproxy->options &= ~PR_O_HTTP_MODE;
4042 curproxy->options |= PR_O_HTTP_KAL;
4043 goto out;
4044 }
4045 else if (kwm == KWM_NO) {
4046 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4047 curproxy->options &= ~PR_O_HTTP_MODE;
4048 goto out;
4049 }
4050 }
4051 else if (strcmp(args[1], "http-tunnel") == 0) {
4052 if (kwm == KWM_STD) {
4053 curproxy->options &= ~PR_O_HTTP_MODE;
4054 curproxy->options |= PR_O_HTTP_TUN;
4055 goto out;
4056 }
4057 else if (kwm == KWM_NO) {
4058 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4059 curproxy->options &= ~PR_O_HTTP_MODE;
4060 goto out;
4061 }
4062 }
4063
Willy Tarreau3842f002009-06-14 11:39:52 +02004064 if (kwm != KWM_STD) {
4065 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004066 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004069 }
4070
Emeric Brun3a058f32009-06-30 18:26:00 +02004071 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004072 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004074 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004075 if (*(args[2]) != '\0') {
4076 if (!strcmp(args[2], "clf")) {
4077 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004078 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004079 } else {
4080 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004083 }
4084 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004085 if (curproxy->conf.logformat_string != default_http_log_format &&
4086 curproxy->conf.logformat_string != default_tcp_log_format &&
4087 curproxy->conf.logformat_string != clf_http_log_format)
4088 free(curproxy->conf.logformat_string);
4089 curproxy->conf.logformat_string = logformat;
4090
4091 free(curproxy->conf.lfs_file);
4092 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4093 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004094 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004095 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004096 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004097 if (curproxy->conf.logformat_string != default_http_log_format &&
4098 curproxy->conf.logformat_string != default_tcp_log_format &&
4099 curproxy->conf.logformat_string != clf_http_log_format)
4100 free(curproxy->conf.logformat_string);
4101 curproxy->conf.logformat_string = default_tcp_log_format;
4102
4103 free(curproxy->conf.lfs_file);
4104 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4105 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107 else if (!strcmp(args[1], "tcpka")) {
4108 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004109 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004111
4112 if (curproxy->cap & PR_CAP_FE)
4113 curproxy->options |= PR_O_TCP_CLI_KA;
4114 if (curproxy->cap & PR_CAP_BE)
4115 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 }
4117 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004118 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004119 err_code |= ERR_WARN;
4120
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004122 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004123 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004124 curproxy->options2 &= ~PR_O2_CHK_ANY;
4125 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 if (!*args[2]) { /* no argument */
4127 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4128 curproxy->check_len = strlen(DEF_CHECK_REQ);
4129 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004130 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 curproxy->check_req = (char *)malloc(reqlen);
4132 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004133 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004135 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 if (*args[4])
4137 reqlen += strlen(args[4]);
4138 else
4139 reqlen += strlen("HTTP/1.0");
4140
4141 curproxy->check_req = (char *)malloc(reqlen);
4142 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004143 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004145 }
4146 else if (!strcmp(args[1], "ssl-hello-chk")) {
4147 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004148 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004150
Willy Tarreaua534fea2008-08-03 12:19:50 +02004151 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004152 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004153 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004154 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 }
Willy Tarreau23677902007-05-08 23:50:35 +02004156 else if (!strcmp(args[1], "smtpchk")) {
4157 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004158 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004159 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004160 curproxy->options2 &= ~PR_O2_CHK_ANY;
4161 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004162
4163 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4164 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4165 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4166 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4167 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4168 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4169 curproxy->check_req = (char *)malloc(reqlen);
4170 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4171 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4172 } else {
4173 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4174 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4175 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4176 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4177 }
4178 }
4179 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004180 else if (!strcmp(args[1], "pgsql-check")) {
4181 /* use PostgreSQL request to check servers' health */
4182 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4183 err_code |= ERR_WARN;
4184
4185 free(curproxy->check_req);
4186 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004187 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004188 curproxy->options2 |= PR_O2_PGSQL_CHK;
4189
4190 if (*(args[2])) {
4191 int cur_arg = 2;
4192
4193 while (*(args[cur_arg])) {
4194 if (strcmp(args[cur_arg], "user") == 0) {
4195 char * packet;
4196 uint32_t packet_len;
4197 uint32_t pv;
4198
4199 /* suboption header - needs additional argument for it */
4200 if (*(args[cur_arg+1]) == 0) {
4201 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4202 file, linenum, args[0], args[1], args[cur_arg]);
4203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
4205 }
4206
4207 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4208 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4209 pv = htonl(0x30000); /* protocol version 3.0 */
4210
4211 packet = (char*) calloc(1, packet_len);
4212
4213 memcpy(packet + 4, &pv, 4);
4214
4215 /* copy "user" */
4216 memcpy(packet + 8, "user", 4);
4217
4218 /* copy username */
4219 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4220
4221 free(curproxy->check_req);
4222 curproxy->check_req = packet;
4223 curproxy->check_len = packet_len;
4224
4225 packet_len = htonl(packet_len);
4226 memcpy(packet, &packet_len, 4);
4227 cur_arg += 2;
4228 } else {
4229 /* unknown suboption - catchall */
4230 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4231 file, linenum, args[0], args[1]);
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235 } /* end while loop */
4236 }
4237 }
4238
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004239 else if (!strcmp(args[1], "redis-check")) {
4240 /* use REDIS PING request to check servers' health */
4241 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4242 err_code |= ERR_WARN;
4243
4244 free(curproxy->check_req);
4245 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004246 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004247 curproxy->options2 |= PR_O2_REDIS_CHK;
4248
4249 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4250 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4251 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4252 }
4253
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004254 else if (!strcmp(args[1], "mysql-check")) {
4255 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004256 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4257 err_code |= ERR_WARN;
4258
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004259 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004260 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004261 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004262 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004263
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004264 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004265 * const char mysql40_client_auth_pkt[] = {
4266 * "\x0e\x00\x00" // packet length
4267 * "\x01" // packet number
4268 * "\x00\x00" // client capabilities
4269 * "\x00\x00\x01" // max packet
4270 * "haproxy\x00" // username (null terminated string)
4271 * "\x00" // filler (always 0x00)
4272 * "\x01\x00\x00" // packet length
4273 * "\x00" // packet number
4274 * "\x01" // COM_QUIT command
4275 * };
4276 */
4277
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004278 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4279 * const char mysql41_client_auth_pkt[] = {
4280 * "\x0e\x00\x00\" // packet length
4281 * "\x01" // packet number
4282 * "\x00\x00\x00\x00" // client capabilities
4283 * "\x00\x00\x00\x01" // max packet
4284 * "\x21" // character set (UTF-8)
4285 * char[23] // All zeroes
4286 * "haproxy\x00" // username (null terminated string)
4287 * "\x00" // filler (always 0x00)
4288 * "\x01\x00\x00" // packet length
4289 * "\x00" // packet number
4290 * "\x01" // COM_QUIT command
4291 * };
4292 */
4293
4294
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004295 if (*(args[2])) {
4296 int cur_arg = 2;
4297
4298 while (*(args[cur_arg])) {
4299 if (strcmp(args[cur_arg], "user") == 0) {
4300 char *mysqluser;
4301 int packetlen, reqlen, userlen;
4302
4303 /* suboption header - needs additional argument for it */
4304 if (*(args[cur_arg+1]) == 0) {
4305 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4306 file, linenum, args[0], args[1], args[cur_arg]);
4307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
4309 }
4310 mysqluser = args[cur_arg + 1];
4311 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004312
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004313 if (*(args[cur_arg+2])) {
4314 if (!strcmp(args[cur_arg+2], "post-41")) {
4315 packetlen = userlen + 7 + 27;
4316 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004317
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004318 free(curproxy->check_req);
4319 curproxy->check_req = (char *)calloc(1, reqlen);
4320 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004321
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004322 snprintf(curproxy->check_req, 4, "%c%c%c",
4323 ((unsigned char) packetlen & 0xff),
4324 ((unsigned char) (packetlen >> 8) & 0xff),
4325 ((unsigned char) (packetlen >> 16) & 0xff));
4326
4327 curproxy->check_req[3] = 1;
4328 curproxy->check_req[5] = 130;
4329 curproxy->check_req[11] = 1;
4330 curproxy->check_req[12] = 33;
4331 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4332 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4333 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4334 cur_arg += 3;
4335 } else {
4336 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
4339 }
4340 } else {
4341 packetlen = userlen + 7;
4342 reqlen = packetlen + 9;
4343
4344 free(curproxy->check_req);
4345 curproxy->check_req = (char *)calloc(1, reqlen);
4346 curproxy->check_len = reqlen;
4347
4348 snprintf(curproxy->check_req, 4, "%c%c%c",
4349 ((unsigned char) packetlen & 0xff),
4350 ((unsigned char) (packetlen >> 8) & 0xff),
4351 ((unsigned char) (packetlen >> 16) & 0xff));
4352
4353 curproxy->check_req[3] = 1;
4354 curproxy->check_req[5] = 128;
4355 curproxy->check_req[8] = 1;
4356 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4357 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4358 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4359 cur_arg += 2;
4360 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004361 } else {
4362 /* unknown suboption - catchall */
4363 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4364 file, linenum, args[0], args[1]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368 } /* end while loop */
4369 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004370 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004371 else if (!strcmp(args[1], "ldap-check")) {
4372 /* use LDAP request to check servers' health */
4373 free(curproxy->check_req);
4374 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004375 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004376 curproxy->options2 |= PR_O2_LDAP_CHK;
4377
4378 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4379 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4380 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4381 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004382 else if (!strcmp(args[1], "tcp-check")) {
4383 /* use raw TCPCHK send/expect to check servers' health */
4384 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4385 err_code |= ERR_WARN;
4386
4387 free(curproxy->check_req);
4388 curproxy->check_req = NULL;
4389 curproxy->options2 &= ~PR_O2_CHK_ANY;
4390 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4391 }
Simon Horman98637e52014-06-20 12:30:16 +09004392 else if (!strcmp(args[1], "external-check")) {
4393 /* excute an external command to check servers' health */
4394 free(curproxy->check_req);
4395 curproxy->check_req = NULL;
4396 curproxy->options2 &= ~PR_O2_CHK_ANY;
4397 curproxy->options2 |= PR_O2_EXT_CHK;
4398 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004399 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004400 int cur_arg;
4401
4402 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4403 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004404 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004405
Willy Tarreau87cf5142011-08-19 22:57:24 +02004406 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004407
4408 free(curproxy->fwdfor_hdr_name);
4409 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4410 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4411
4412 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4413 cur_arg = 2;
4414 while (*(args[cur_arg])) {
4415 if (!strcmp(args[cur_arg], "except")) {
4416 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004417 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004418 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4419 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004422 }
4423 /* flush useless bits */
4424 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004425 cur_arg += 2;
4426 } else if (!strcmp(args[cur_arg], "header")) {
4427 /* suboption header - needs additional argument for it */
4428 if (*(args[cur_arg+1]) == 0) {
4429 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4430 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004433 }
4434 free(curproxy->fwdfor_hdr_name);
4435 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4436 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4437 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004438 } else if (!strcmp(args[cur_arg], "if-none")) {
4439 curproxy->options &= ~PR_O_FF_ALWAYS;
4440 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004441 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004442 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004443 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004444 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004447 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004448 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004449 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004450 else if (!strcmp(args[1], "originalto")) {
4451 int cur_arg;
4452
4453 /* insert x-original-to field, but not for the IP address listed as an except.
4454 * set default options (ie: bitfield, header name, etc)
4455 */
4456
4457 curproxy->options |= PR_O_ORGTO;
4458
4459 free(curproxy->orgto_hdr_name);
4460 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4461 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4462
Willy Tarreau87cf5142011-08-19 22:57:24 +02004463 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004464 cur_arg = 2;
4465 while (*(args[cur_arg])) {
4466 if (!strcmp(args[cur_arg], "except")) {
4467 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004468 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 +02004469 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4470 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004473 }
4474 /* flush useless bits */
4475 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4476 cur_arg += 2;
4477 } else if (!strcmp(args[cur_arg], "header")) {
4478 /* suboption header - needs additional argument for it */
4479 if (*(args[cur_arg+1]) == 0) {
4480 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4481 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004484 }
4485 free(curproxy->orgto_hdr_name);
4486 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4487 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4488 cur_arg += 2;
4489 } else {
4490 /* unknown suboption - catchall */
4491 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4492 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004495 }
4496 } /* end while loop */
4497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 else {
4499 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 }
Willy Tarreau93893792009-07-23 13:19:11 +02004503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004505 else if (!strcmp(args[0], "default_backend")) {
4506 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004508
4509 if (*(args[1]) == 0) {
4510 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004513 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004514 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004515 curproxy->defbe.name = strdup(args[1]);
4516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004520
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004521 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4522 Warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'option redispatch', and will not be supported by future versions.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004523 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 /* enable reconnections to dispatch */
4526 curproxy->options |= PR_O_REDISP;
4527 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004528 else if (!strcmp(args[0], "http-check")) {
4529 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004531
4532 if (strcmp(args[1], "disable-on-404") == 0) {
4533 /* enable a graceful server shutdown on an HTTP 404 response */
4534 curproxy->options |= PR_O_DISABLE404;
4535 }
Willy Tarreauef781042010-01-27 11:53:01 +01004536 else if (strcmp(args[1], "send-state") == 0) {
4537 /* enable emission of the apparent state of a server in HTTP checks */
4538 curproxy->options2 |= PR_O2_CHK_SNDST;
4539 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004540 else if (strcmp(args[1], "expect") == 0) {
4541 const char *ptr_arg;
4542 int cur_arg;
4543
4544 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4545 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
4548 }
4549
4550 cur_arg = 2;
4551 /* consider exclamation marks, sole or at the beginning of a word */
4552 while (*(ptr_arg = args[cur_arg])) {
4553 while (*ptr_arg == '!') {
4554 curproxy->options2 ^= PR_O2_EXP_INV;
4555 ptr_arg++;
4556 }
4557 if (*ptr_arg)
4558 break;
4559 cur_arg++;
4560 }
4561 /* now ptr_arg points to the beginning of a word past any possible
4562 * exclamation mark, and cur_arg is the argument which holds this word.
4563 */
4564 if (strcmp(ptr_arg, "status") == 0) {
4565 if (!*(args[cur_arg + 1])) {
4566 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4567 file, linenum, args[0], args[1], ptr_arg);
4568 err_code |= ERR_ALERT | ERR_FATAL;
4569 goto out;
4570 }
4571 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004572 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004573 curproxy->expect_str = strdup(args[cur_arg + 1]);
4574 }
4575 else if (strcmp(ptr_arg, "string") == 0) {
4576 if (!*(args[cur_arg + 1])) {
4577 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4578 file, linenum, args[0], args[1], ptr_arg);
4579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
4581 }
4582 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004583 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004584 curproxy->expect_str = strdup(args[cur_arg + 1]);
4585 }
4586 else if (strcmp(ptr_arg, "rstatus") == 0) {
4587 if (!*(args[cur_arg + 1])) {
4588 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4589 file, linenum, args[0], args[1], ptr_arg);
4590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
4592 }
4593 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004594 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004595 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004596 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004597 free(curproxy->expect_regex);
4598 curproxy->expect_regex = NULL;
4599 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004600 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004601 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4602 error = NULL;
4603 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4604 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4605 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4606 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609 }
4610 }
4611 else if (strcmp(ptr_arg, "rstring") == 0) {
4612 if (!*(args[cur_arg + 1])) {
4613 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4614 file, linenum, args[0], args[1], ptr_arg);
4615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617 }
4618 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004619 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004620 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004621 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004622 free(curproxy->expect_regex);
4623 curproxy->expect_regex = NULL;
4624 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004625 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004626 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4627 error = NULL;
4628 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4629 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4630 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4631 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635 }
4636 else {
4637 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4638 file, linenum, args[0], args[1], ptr_arg);
4639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004643 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004644 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 +02004645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004647 }
4648 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004649 else if (!strcmp(args[0], "tcp-check")) {
4650 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4651 err_code |= ERR_WARN;
4652
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004653 if (strcmp(args[1], "connect") == 0) {
4654 const char *ptr_arg;
4655 int cur_arg;
4656 struct tcpcheck_rule *tcpcheck;
4657 struct list *l;
4658
4659 /* check if first rule is also a 'connect' action */
4660 l = (struct list *)&curproxy->tcpcheck_rules;
4661 if (l->p != l->n) {
4662 tcpcheck = (struct tcpcheck_rule *)l->n;
4663 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4664 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4665 file, linenum);
4666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
4668 }
4669 }
4670
4671 cur_arg = 2;
4672 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4673 tcpcheck->action = TCPCHK_ACT_CONNECT;
4674
4675 /* parsing each parameters to fill up the rule */
4676 while (*(ptr_arg = args[cur_arg])) {
4677 /* tcp port */
4678 if (strcmp(args[cur_arg], "port") == 0) {
4679 if ( (atol(args[cur_arg + 1]) > 65535) ||
4680 (atol(args[cur_arg + 1]) < 1) ){
4681 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4682 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
4686 tcpcheck->port = atol(args[cur_arg + 1]);
4687 cur_arg += 2;
4688 }
4689 /* send proxy protocol */
4690 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4691 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4692 cur_arg++;
4693 }
4694#ifdef USE_OPENSSL
4695 else if (strcmp(args[cur_arg], "ssl") == 0) {
4696 curproxy->options |= PR_O_TCPCHK_SSL;
4697 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4698 cur_arg++;
4699 }
4700#endif /* USE_OPENSSL */
4701 else {
4702#ifdef USE_OPENSSL
4703 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4704#else /* USE_OPENSSL */
4705 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4706#endif /* USE_OPENSSL */
4707 file, linenum, args[0], args[1], args[cur_arg]);
4708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
4711
4712 }
4713
4714 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4715 }
4716 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004717 if (! *(args[2]) ) {
4718 /* SEND string expected */
4719 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4720 file, linenum, args[0], args[1], args[2]);
4721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
4723 } else {
4724 struct tcpcheck_rule *tcpcheck;
4725
4726 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4727
4728 tcpcheck->action = TCPCHK_ACT_SEND;
4729 tcpcheck->string_len = strlen(args[2]);
4730 tcpcheck->string = strdup(args[2]);
4731 tcpcheck->expect_regex = NULL;
4732
4733 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4734 }
4735 }
4736 else if (strcmp(args[1], "send-binary") == 0) {
4737 if (! *(args[2]) ) {
4738 /* SEND binary string expected */
4739 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4740 file, linenum, args[0], args[1], args[2]);
4741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 } else {
4744 struct tcpcheck_rule *tcpcheck;
4745 char *err = NULL;
4746
4747 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4748
4749 tcpcheck->action = TCPCHK_ACT_SEND;
4750 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4751 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4752 file, linenum, args[0], args[1], args[2], err);
4753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
4755 }
4756 tcpcheck->expect_regex = NULL;
4757
4758 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4759 }
4760 }
4761 else if (strcmp(args[1], "expect") == 0) {
4762 const char *ptr_arg;
4763 int cur_arg;
4764 int inverse = 0;
4765
4766 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4767 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4768 err_code |= ERR_ALERT | ERR_FATAL;
4769 goto out;
4770 }
4771
4772 cur_arg = 2;
4773 /* consider exclamation marks, sole or at the beginning of a word */
4774 while (*(ptr_arg = args[cur_arg])) {
4775 while (*ptr_arg == '!') {
4776 inverse = !inverse;
4777 ptr_arg++;
4778 }
4779 if (*ptr_arg)
4780 break;
4781 cur_arg++;
4782 }
4783 /* now ptr_arg points to the beginning of a word past any possible
4784 * exclamation mark, and cur_arg is the argument which holds this word.
4785 */
4786 if (strcmp(ptr_arg, "binary") == 0) {
4787 if (!*(args[cur_arg + 1])) {
4788 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4789 file, linenum, args[0], args[1], ptr_arg);
4790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
4792 }
4793 struct tcpcheck_rule *tcpcheck;
4794 char *err = NULL;
4795
4796 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4797
4798 tcpcheck->action = TCPCHK_ACT_EXPECT;
4799 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4800 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4801 file, linenum, args[0], args[1], args[2], err);
4802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
4804 }
4805 tcpcheck->expect_regex = NULL;
4806 tcpcheck->inverse = inverse;
4807
4808 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4809 }
4810 else if (strcmp(ptr_arg, "string") == 0) {
4811 if (!*(args[cur_arg + 1])) {
4812 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4813 file, linenum, args[0], args[1], ptr_arg);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
4817 struct tcpcheck_rule *tcpcheck;
4818
4819 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4820
4821 tcpcheck->action = TCPCHK_ACT_EXPECT;
4822 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4823 tcpcheck->string = strdup(args[cur_arg + 1]);
4824 tcpcheck->expect_regex = NULL;
4825 tcpcheck->inverse = inverse;
4826
4827 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4828 }
4829 else if (strcmp(ptr_arg, "rstring") == 0) {
4830 if (!*(args[cur_arg + 1])) {
4831 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4832 file, linenum, args[0], args[1], ptr_arg);
4833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
4835 }
4836 struct tcpcheck_rule *tcpcheck;
4837
4838 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4839
4840 tcpcheck->action = TCPCHK_ACT_EXPECT;
4841 tcpcheck->string_len = 0;
4842 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004843 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4844 error = NULL;
4845 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4846 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4847 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4848 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
4852 tcpcheck->inverse = inverse;
4853
4854 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4855 }
4856 else {
4857 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4858 file, linenum, args[0], args[1], ptr_arg);
4859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
4861 }
4862 }
4863 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004864 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
4868 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004869 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004870 if (curproxy == &defproxy) {
4871 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004874 }
4875
Willy Tarreaub80c2302007-11-30 20:51:32 +01004876 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004877 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004878
4879 if (strcmp(args[1], "fail") == 0) {
4880 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004881 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004882 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4883 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004886 }
4887
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004888 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4889 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4890 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004893 }
4894 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4895 }
4896 else {
4897 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004900 }
4901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902#ifdef TPROXY
4903 else if (!strcmp(args[0], "transparent")) {
4904 /* enable transparent proxy connections */
4905 curproxy->options |= PR_O_TRANSP;
4906 }
4907#endif
4908 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004909 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004910 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004911
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 if (*(args[1]) == 0) {
4913 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 curproxy->maxconn = atol(args[1]);
4918 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004919 else if (!strcmp(args[0], "backlog")) { /* backlog */
4920 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004922
4923 if (*(args[1]) == 0) {
4924 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004927 }
4928 curproxy->backlog = atol(args[1]);
4929 }
Willy Tarreau86034312006-12-29 00:10:33 +01004930 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004932 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004933
Willy Tarreau86034312006-12-29 00:10:33 +01004934 if (*(args[1]) == 0) {
4935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004938 }
4939 curproxy->fullconn = atol(args[1]);
4940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4942 if (*(args[1]) == 0) {
4943 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004947 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4948 if (err) {
4949 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4950 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004953 }
4954 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
4956 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004957 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004958 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004959 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 if (curproxy == &defproxy) {
4962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004966 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004968
Willy Tarreau902636f2013-03-10 19:44:48 +01004969 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004970 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004971 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004972 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004973 goto out;
4974 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004975
4976 proto = protocol_by_family(sk->ss_family);
4977 if (!proto || !proto->connect) {
4978 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4979 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
4982 }
4983
4984 if (port1 != port2) {
4985 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4986 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004990
4991 if (!port1) {
4992 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4993 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004997
Willy Tarreaud5191e72010-02-09 20:50:45 +01004998 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004999 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005002 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005004
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005005 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5006 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005011 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005012 /**
5013 * The syntax for hash-type config element is
5014 * hash-type {map-based|consistent} [[<algo>] avalanche]
5015 *
5016 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5017 */
5018 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005019
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005020 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5021 err_code |= ERR_WARN;
5022
5023 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005024 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5025 }
5026 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005027 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5028 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005029 else if (strcmp(args[1], "avalanche") == 0) {
5030 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]);
5031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005033 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005034 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005035 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
5038 }
Bhaskar98634f02013-10-29 23:30:51 -04005039
5040 /* set the hash function to use */
5041 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005042 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005043 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005044
5045 /* if consistent with no argument, then avalanche modifier is also applied */
5046 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5047 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005048 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005049 /* set the hash function */
5050 if (!strcmp(args[2], "sdbm")) {
5051 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5052 }
5053 else if (!strcmp(args[2], "djb2")) {
5054 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005055 }
5056 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005057 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005058 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005059 else if (!strcmp(args[2], "crc32")) {
5060 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5061 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005062 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005063 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
5066 }
5067
5068 /* set the hash modifier */
5069 if (!strcmp(args[3], "avalanche")) {
5070 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5071 }
5072 else if (*args[3]) {
5073 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
5076 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005077 }
William Lallemanda73203e2012-03-12 12:48:57 +01005078 }
William Lallemanda73203e2012-03-12 12:48:57 +01005079 else if (strcmp(args[0], "unique-id-format") == 0) {
5080 if (!*(args[1])) {
5081 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
5084 }
William Lallemand3203ff42012-11-11 17:30:56 +01005085 if (*(args[2])) {
5086 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
5089 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005090 free(curproxy->conf.uniqueid_format_string);
5091 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005092
Willy Tarreau62a61232013-04-12 18:13:46 +02005093 free(curproxy->conf.uif_file);
5094 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5095 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005096 }
William Lallemanda73203e2012-03-12 12:48:57 +01005097
5098 else if (strcmp(args[0], "unique-id-header") == 0) {
5099 if (!*(args[1])) {
5100 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
5103 }
5104 free(curproxy->header_unique_id);
5105 curproxy->header_unique_id = strdup(args[1]);
5106 }
5107
William Lallemand723b73a2012-02-08 16:37:49 +01005108 else if (strcmp(args[0], "log-format") == 0) {
5109 if (!*(args[1])) {
5110 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
5113 }
William Lallemand3203ff42012-11-11 17:30:56 +01005114 if (*(args[2])) {
5115 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
5118 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005119
Willy Tarreau62a61232013-04-12 18:13:46 +02005120 if (curproxy->conf.logformat_string != default_http_log_format &&
5121 curproxy->conf.logformat_string != default_tcp_log_format &&
5122 curproxy->conf.logformat_string != clf_http_log_format)
5123 free(curproxy->conf.logformat_string);
5124 curproxy->conf.logformat_string = strdup(args[1]);
5125
5126 free(curproxy->conf.lfs_file);
5127 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5128 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005129
5130 /* get a chance to improve log-format error reporting by
5131 * reporting the correct line-number when possible.
5132 */
5133 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5134 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5135 file, linenum, curproxy->id);
5136 err_code |= ERR_WARN;
5137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005139 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5140 if (*(args[1]) == 0) {
5141 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
5144 }
5145 free(curproxy->log_tag);
5146 curproxy->log_tag = strdup(args[1]);
5147 }
William Lallemand0f99e342011-10-12 17:50:54 +02005148 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5149 /* delete previous herited or defined syslog servers */
5150 struct logsrv *back;
5151
5152 if (*(args[1]) != 0) {
5153 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
5156 }
5157
William Lallemand723b73a2012-02-08 16:37:49 +01005158 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5159 LIST_DEL(&tmplogsrv->list);
5160 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005161 }
5162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005164 struct logsrv *logsrv;
5165
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005167 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005168 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005169 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005170 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005171 LIST_INIT(&node->list);
5172 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
5175 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005176 struct sockaddr_storage *sk;
5177 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005178 int arg = 0;
5179 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005180
5181 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182
Willy Tarreau18324f52014-06-27 18:10:07 +02005183 /* just after the address, a length may be specified */
5184 if (strcmp(args[arg+2], "len") == 0) {
5185 len = atoi(args[arg+3]);
5186 if (len < 80 || len > 65535) {
5187 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5188 file, linenum, args[arg+3]);
5189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
5191 }
5192 logsrv->maxlen = len;
5193
5194 /* skip these two args */
5195 arg += 2;
5196 }
5197 else
5198 logsrv->maxlen = MAX_SYSLOG_LEN;
5199
5200 if (logsrv->maxlen > global.max_syslog_len) {
5201 global.max_syslog_len = logsrv->maxlen;
5202 logline = realloc(logline, global.max_syslog_len + 1);
5203 }
5204
5205 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005206 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005207 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
5210
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 }
5212
William Lallemand0f99e342011-10-12 17:50:54 +02005213 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005214 if (*(args[arg+3])) {
5215 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005216 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005217 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
5222 }
5223
William Lallemand0f99e342011-10-12 17:50:54 +02005224 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005225 if (*(args[arg+4])) {
5226 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005227 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005228 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005232 }
5233 }
5234
Willy Tarreau902636f2013-03-10 19:44:48 +01005235 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005236 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005237 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005238 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005239 goto out;
5240 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005241
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005242 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005243
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005244 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005245 if (port1 != port2) {
5246 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5247 file, linenum, args[0], args[1]);
5248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005252 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005253 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
William Lallemand0f99e342011-10-12 17:50:54 +02005255
5256 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
5258 else {
5259 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5260 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
5264 }
5265 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005266 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005267 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005268 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005269 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005270
Willy Tarreau977b8e42006-12-29 14:19:17 +01005271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005273
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005275 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5276 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005280
5281 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005282 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5283 free(curproxy->conn_src.iface_name);
5284 curproxy->conn_src.iface_name = NULL;
5285 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005286
Willy Tarreau902636f2013-03-10 19:44:48 +01005287 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005288 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005289 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005290 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005291 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005292 goto out;
5293 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005294
5295 proto = protocol_by_family(sk->ss_family);
5296 if (!proto || !proto->connect) {
5297 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005298 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
5301 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005302
5303 if (port1 != port2) {
5304 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5305 file, linenum, args[0], args[1]);
5306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
5308 }
5309
Willy Tarreauef9a3602012-12-08 22:29:20 +01005310 curproxy->conn_src.source_addr = *sk;
5311 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005312
5313 cur_arg = 2;
5314 while (*(args[cur_arg])) {
5315 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005316#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5317#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005318 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005319 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5320 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005323 }
5324#endif
5325 if (!*args[cur_arg + 1]) {
5326 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5327 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005330 }
5331
5332 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005333 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5334 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005335 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005336 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5337 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005338 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5339 char *name, *end;
5340
5341 name = args[cur_arg+1] + 7;
5342 while (isspace(*name))
5343 name++;
5344
5345 end = name;
5346 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5347 end++;
5348
Willy Tarreauef9a3602012-12-08 22:29:20 +01005349 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5350 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5351 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5352 curproxy->conn_src.bind_hdr_len = end - name;
5353 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5354 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5355 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005356
5357 /* now look for an occurrence number */
5358 while (isspace(*end))
5359 end++;
5360 if (*end == ',') {
5361 end++;
5362 name = end;
5363 if (*end == '-')
5364 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005365 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005366 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005367 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005368 }
5369
Willy Tarreauef9a3602012-12-08 22:29:20 +01005370 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005371 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5372 " occurrences values smaller than %d.\n",
5373 file, linenum, MAX_HDR_HISTORY);
5374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005377 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005378 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005379
Willy Tarreau902636f2013-03-10 19:44:48 +01005380 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005381 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005382 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005383 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005384 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005385 goto out;
5386 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005387
5388 proto = protocol_by_family(sk->ss_family);
5389 if (!proto || !proto->connect) {
5390 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5391 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005395
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005396 if (port1 != port2) {
5397 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5398 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005402 curproxy->conn_src.tproxy_addr = *sk;
5403 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005404 }
5405 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005406#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005407 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005408#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005409#else /* no TPROXY support */
5410 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005411 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005414#endif
5415 cur_arg += 2;
5416 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005417 }
5418
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005419 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5420#ifdef SO_BINDTODEVICE
5421 if (!*args[cur_arg + 1]) {
5422 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5423 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005426 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005427 free(curproxy->conn_src.iface_name);
5428 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5429 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005430 global.last_checks |= LSTCHK_NETADM;
5431#else
5432 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5433 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005436#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005437 cur_arg += 2;
5438 continue;
5439 }
5440 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005441 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005445 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005446 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5447 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5448 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005453 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005459
5460 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005461 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005462 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005463 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465 }
5466 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005467 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005468 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005469 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005470 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 }
5473 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005474 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005475 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005476 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005477 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
5480 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005481 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005482 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005483 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005484 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 }
5487 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005488 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005489 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005490 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005491 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005494 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005495 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005496 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005497 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005498 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005499 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005500 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005501 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005502 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005503 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005504 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005505 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005506 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005507
5508 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5509 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005510 }
5511 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005513 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005514 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005516 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005517
5518 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5519 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005522 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5524 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005528
5529 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005530 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005531 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005532 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005534 }
5535 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005536 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005537 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005538 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005539 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 }
5542 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005543 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005544 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005545 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005546 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 }
5549 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005550 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005551 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005552 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005553 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555 }
5556 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005557 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005558 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005559 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005560 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005563 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005564 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005565 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005566 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005567 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005568 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005571 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005572
Willy Tarreaubaaee002006-06-26 02:48:02 +02005573 if (curproxy == &defproxy) {
5574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005578 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005579 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581 if (*(args[1]) == 0) {
5582 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005586
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005587 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005588 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5589 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5590 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
5593 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005594 err_code |= warnif_cond_conflicts(cond,
5595 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5596 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005597 }
5598 else if (*args[2]) {
5599 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5600 file, linenum, args[0], args[2]);
5601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
5603 }
5604
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005605 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005606 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005607 wl->s = strdup(args[1]);
5608 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005609 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 }
5611 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005612 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5614 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005618
Willy Tarreauade5ec42010-01-28 19:33:49 +01005619 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005620 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005621 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005622 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 }
5625 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005626 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005627 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005628 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005629 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 }
5632 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005633 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005634 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005635 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005636 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 }
5639 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005640 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 }
5646
Willy Tarreauade5ec42010-01-28 19:33:49 +01005647 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005648 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005649 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005650 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 }
5653 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005654 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005655 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005656 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005657 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 }
5660 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005661 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005662 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005663 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005664 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 }
5667 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005668 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005669
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 if (curproxy == &defproxy) {
5671 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005675 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005676 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677
Willy Tarreaubaaee002006-06-26 02:48:02 +02005678 if (*(args[1]) == 0) {
5679 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 }
5683
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005684 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005685 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5686 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5687 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005691 err_code |= warnif_cond_conflicts(cond,
5692 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5693 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005694 }
5695 else if (*args[2]) {
5696 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5697 file, linenum, args[0], args[2]);
5698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
5701
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005702 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005703 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005704 wl->s = strdup(args[1]);
5705 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 }
5707 else if (!strcmp(args[0], "errorloc") ||
5708 !strcmp(args[0], "errorloc302") ||
5709 !strcmp(args[0], "errorloc303")) { /* error location */
5710 int errnum, errlen;
5711 char *err;
5712
Willy Tarreau977b8e42006-12-29 14:19:17 +01005713 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005714 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005715
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005717 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
5721
5722 errnum = atol(args[1]);
5723 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005724 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5725 err = malloc(errlen);
5726 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005728 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5729 err = malloc(errlen);
5730 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 }
5732
Willy Tarreau0f772532006-12-23 20:51:41 +01005733 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5734 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005735 chunk_destroy(&curproxy->errmsg[rc]);
5736 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005737 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005740
5741 if (rc >= HTTP_ERR_SIZE) {
5742 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5743 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 free(err);
5745 }
5746 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005747 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5748 int errnum, errlen, fd;
5749 char *err;
5750 struct stat stat;
5751
5752 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005753 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005754
5755 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005756 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005757 err_code |= ERR_ALERT | ERR_FATAL;
5758 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005759 }
5760
5761 fd = open(args[2], O_RDONLY);
5762 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5763 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5764 file, linenum, args[2], args[1]);
5765 if (fd >= 0)
5766 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005769 }
5770
Willy Tarreau27a674e2009-08-17 07:23:33 +02005771 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005772 errlen = stat.st_size;
5773 } else {
5774 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005775 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005777 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005778 }
5779
5780 err = malloc(errlen); /* malloc() must succeed during parsing */
5781 errnum = read(fd, err, errlen);
5782 if (errnum != errlen) {
5783 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5784 file, linenum, args[2], args[1]);
5785 close(fd);
5786 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005787 err_code |= ERR_ALERT | ERR_FATAL;
5788 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005789 }
5790 close(fd);
5791
5792 errnum = atol(args[1]);
5793 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5794 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005795 chunk_destroy(&curproxy->errmsg[rc]);
5796 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005797 break;
5798 }
5799 }
5800
5801 if (rc >= HTTP_ERR_SIZE) {
5802 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5803 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005804 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005805 free(err);
5806 }
5807 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005808 else if (!strcmp(args[0], "compression")) {
5809 struct comp *comp;
5810 if (curproxy->comp == NULL) {
5811 comp = calloc(1, sizeof(struct comp));
5812 curproxy->comp = comp;
5813 } else {
5814 comp = curproxy->comp;
5815 }
5816
5817 if (!strcmp(args[1], "algo")) {
5818 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005819 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005820
William Lallemand82fe75c2012-10-23 10:25:10 +02005821 cur_arg = 2;
5822 if (!*args[cur_arg]) {
5823 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5824 file, linenum, args[0]);
5825 err_code |= ERR_ALERT | ERR_FATAL;
5826 goto out;
5827 }
5828 while (*(args[cur_arg])) {
5829 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5830 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5831 file, linenum, args[0], args[cur_arg]);
5832 err_code |= ERR_ALERT | ERR_FATAL;
5833 goto out;
5834 }
William Lallemand552df672012-11-07 13:21:47 +01005835 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5836 curproxy->comp->algos->end(&ctx);
5837 } else {
5838 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5839 file, linenum, args[0], args[cur_arg]);
5840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
5842 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005843 cur_arg ++;
5844 continue;
5845 }
5846 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005847 else if (!strcmp(args[1], "offload")) {
5848 comp->offload = 1;
5849 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005850 else if (!strcmp(args[1], "type")) {
5851 int cur_arg;
5852 cur_arg = 2;
5853 if (!*args[cur_arg]) {
5854 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5855 file, linenum, args[0]);
5856 err_code |= ERR_ALERT | ERR_FATAL;
5857 goto out;
5858 }
5859 while (*(args[cur_arg])) {
5860 comp_append_type(comp, args[cur_arg]);
5861 cur_arg ++;
5862 continue;
5863 }
5864 }
5865 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005866 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005867 file, linenum, args[0]);
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
5870 }
5871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005873 struct cfg_kw_list *kwl;
5874 int index;
5875
5876 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5877 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5878 if (kwl->kw[index].section != CFG_LISTEN)
5879 continue;
5880 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5881 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005882 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005883 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005884 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005887 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005888 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005889 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005890 err_code |= ERR_WARN;
5891 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005892 }
Willy Tarreau93893792009-07-23 13:19:11 +02005893 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005894 }
5895 }
5896 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005897
Willy Tarreau6daf3432008-01-22 16:44:08 +01005898 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 }
Willy Tarreau93893792009-07-23 13:19:11 +02005902 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005903 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005904 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905}
5906
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005907int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005908cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5909{
5910#ifdef CONFIG_HAP_NS
5911 const char *err;
5912 const char *item = args[0];
5913
5914 if (!strcmp(item, "namespace_list")) {
5915 return 0;
5916 }
5917 else if (!strcmp(item, "namespace")) {
5918 size_t idx = 1;
5919 const char *current;
5920 while (*(current = args[idx++])) {
5921 err = invalid_char(current);
5922 if (err) {
5923 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5924 file, linenum, *err, item, current);
5925 return ERR_ALERT | ERR_FATAL;
5926 }
5927
5928 if (netns_store_lookup(current, strlen(current))) {
5929 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5930 file, linenum, current);
5931 return ERR_ALERT | ERR_FATAL;
5932 }
5933 if (!netns_store_insert(current)) {
5934 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5935 file, linenum, current);
5936 return ERR_ALERT | ERR_FATAL;
5937 }
5938 }
5939 }
5940
5941 return 0;
5942#else
5943 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5944 file, linenum);
5945 return ERR_ALERT | ERR_FATAL;
5946#endif
5947}
5948
5949int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005950cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5951{
5952
5953 int err_code = 0;
5954 const char *err;
5955
5956 if (!strcmp(args[0], "userlist")) { /* new userlist */
5957 struct userlist *newul;
5958
5959 if (!*args[1]) {
5960 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5961 file, linenum, args[0]);
5962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
5965
5966 err = invalid_char(args[1]);
5967 if (err) {
5968 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5969 file, linenum, *err, args[0], args[1]);
5970 err_code |= ERR_ALERT | ERR_FATAL;
5971 goto out;
5972 }
5973
5974 for (newul = userlist; newul; newul = newul->next)
5975 if (!strcmp(newul->name, args[1])) {
5976 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5977 file, linenum, args[1]);
5978 err_code |= ERR_WARN;
5979 goto out;
5980 }
5981
5982 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5983 if (!newul) {
5984 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5985 err_code |= ERR_ALERT | ERR_ABORT;
5986 goto out;
5987 }
5988
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005989 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005990 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005991 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5992 err_code |= ERR_ALERT | ERR_ABORT;
5993 goto out;
5994 }
5995
5996 newul->next = userlist;
5997 userlist = newul;
5998
5999 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006000 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006001 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006002 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006003
6004 if (!*args[1]) {
6005 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6006 file, linenum, args[0]);
6007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
6009 }
6010
6011 err = invalid_char(args[1]);
6012 if (err) {
6013 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6014 file, linenum, *err, args[0], args[1]);
6015 err_code |= ERR_ALERT | ERR_FATAL;
6016 goto out;
6017 }
6018
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006019 for (ag = userlist->groups; ag; ag = ag->next)
6020 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006021 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6022 file, linenum, args[1], userlist->name);
6023 err_code |= ERR_ALERT;
6024 goto out;
6025 }
6026
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006027 ag = calloc(1, sizeof(*ag));
6028 if (!ag) {
6029 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6030 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006031 goto out;
6032 }
6033
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006034 ag->name = strdup(args[1]);
6035 if (!ag) {
6036 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6037 err_code |= ERR_ALERT | ERR_ABORT;
6038 goto out;
6039 }
6040
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006041 cur_arg = 2;
6042
6043 while (*args[cur_arg]) {
6044 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006045 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006046 cur_arg += 2;
6047 continue;
6048 } else {
6049 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6050 file, linenum, args[0]);
6051 err_code |= ERR_ALERT | ERR_FATAL;
6052 goto out;
6053 }
6054 }
6055
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006056 ag->next = userlist->groups;
6057 userlist->groups = ag;
6058
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006059 } else if (!strcmp(args[0], "user")) { /* new user */
6060 struct auth_users *newuser;
6061 int cur_arg;
6062
6063 if (!*args[1]) {
6064 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6065 file, linenum, args[0]);
6066 err_code |= ERR_ALERT | ERR_FATAL;
6067 goto out;
6068 }
6069
6070 for (newuser = userlist->users; newuser; newuser = newuser->next)
6071 if (!strcmp(newuser->user, args[1])) {
6072 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6073 file, linenum, args[1], userlist->name);
6074 err_code |= ERR_ALERT;
6075 goto out;
6076 }
6077
6078 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6079 if (!newuser) {
6080 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6081 err_code |= ERR_ALERT | ERR_ABORT;
6082 goto out;
6083 }
6084
6085 newuser->user = strdup(args[1]);
6086
6087 newuser->next = userlist->users;
6088 userlist->users = newuser;
6089
6090 cur_arg = 2;
6091
6092 while (*args[cur_arg]) {
6093 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006094#ifdef CONFIG_HAP_CRYPT
6095 if (!crypt("", args[cur_arg + 1])) {
6096 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6097 file, linenum, newuser->user);
6098 err_code |= ERR_ALERT | ERR_FATAL;
6099 goto out;
6100 }
6101#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006102 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6103 file, linenum);
6104 err_code |= ERR_ALERT;
6105#endif
6106 newuser->pass = strdup(args[cur_arg + 1]);
6107 cur_arg += 2;
6108 continue;
6109 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6110 newuser->pass = strdup(args[cur_arg + 1]);
6111 newuser->flags |= AU_O_INSECURE;
6112 cur_arg += 2;
6113 continue;
6114 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006115 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006116 cur_arg += 2;
6117 continue;
6118 } else {
6119 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6120 file, linenum, args[0]);
6121 err_code |= ERR_ALERT | ERR_FATAL;
6122 goto out;
6123 }
6124 }
6125 } else {
6126 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6127 err_code |= ERR_ALERT | ERR_FATAL;
6128 }
6129
6130out:
6131 return err_code;
6132}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006133
6134/*
6135 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006136 * Returns the error code, 0 if OK, or any combination of :
6137 * - ERR_ABORT: must abort ASAP
6138 * - ERR_FATAL: we can continue parsing but not start the service
6139 * - ERR_WARN: a warning has been emitted
6140 * - ERR_ALERT: an alert has been emitted
6141 * Only the two first ones can stop processing, the two others are just
6142 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006143 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006144int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006145{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006146 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006147 FILE *f;
6148 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006149 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006150 struct cfg_section *cs = NULL;
6151 struct cfg_section *ics;
6152
6153 /* Register internal sections */
6154 if (!cfg_register_section("listen", cfg_parse_listen) ||
6155 !cfg_register_section("frontend", cfg_parse_listen) ||
6156 !cfg_register_section("backend", cfg_parse_listen) ||
6157 !cfg_register_section("ruleset", cfg_parse_listen) ||
6158 !cfg_register_section("defaults", cfg_parse_listen) ||
6159 !cfg_register_section("global", cfg_parse_global) ||
6160 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006161 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006162 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006163 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006164 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006165
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 if ((f=fopen(file,"r")) == NULL)
6167 return -1;
6168
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006169 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006170 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006171 char *end;
6172 char *args[MAX_LINE_ARGS + 1];
6173 char *line = thisline;
6174
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 linenum++;
6176
6177 end = line + strlen(line);
6178
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006179 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6180 /* Check if we reached the limit and the last char is not \n.
6181 * Watch out for the last line without the terminating '\n'!
6182 */
6183 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006184 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006185 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006186 }
6187
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006189 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 line++;
6191
6192 arg = 0;
6193 args[arg] = line;
6194
6195 while (*line && arg < MAX_LINE_ARGS) {
6196 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6197 * C equivalent value. Other combinations left unchanged (eg: \1).
6198 */
6199 if (*line == '\\') {
6200 int skip = 0;
6201 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6202 *line = line[1];
6203 skip = 1;
6204 }
6205 else if (line[1] == 'r') {
6206 *line = '\r';
6207 skip = 1;
6208 }
6209 else if (line[1] == 'n') {
6210 *line = '\n';
6211 skip = 1;
6212 }
6213 else if (line[1] == 't') {
6214 *line = '\t';
6215 skip = 1;
6216 }
6217 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006218 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 unsigned char hex1, hex2;
6220 hex1 = toupper(line[2]) - '0';
6221 hex2 = toupper(line[3]) - '0';
6222 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6223 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6224 *line = (hex1<<4) + hex2;
6225 skip = 3;
6226 }
6227 else {
6228 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006229 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 }
6231 }
6232 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006233 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006234 end -= skip;
6235 }
6236 line++;
6237 }
6238 else if (*line == '#' || *line == '\n' || *line == '\r') {
6239 /* end of string, end of loop */
6240 *line = 0;
6241 break;
6242 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006243 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006245 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006246 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006247 line++;
6248 args[++arg] = line;
6249 }
6250 else {
6251 line++;
6252 }
6253 }
6254
6255 /* empty line */
6256 if (!**args)
6257 continue;
6258
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006259 if (*line) {
6260 /* we had to stop due to too many args.
6261 * Let's terminate the string, print the offending part then cut the
6262 * last arg.
6263 */
6264 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6265 line++;
6266 *line = '\0';
6267
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006268 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006269 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006270 err_code |= ERR_ALERT | ERR_FATAL;
6271 args[arg] = line;
6272 }
6273
Willy Tarreau540abe42007-05-02 20:50:16 +02006274 /* zero out remaining args and ensure that at least one entry
6275 * is zeroed out.
6276 */
6277 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006278 args[arg] = line;
6279 }
6280
Willy Tarreau3842f002009-06-14 11:39:52 +02006281 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006282 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006283 char *tmp;
6284
Willy Tarreau3842f002009-06-14 11:39:52 +02006285 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006286 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006287 for (arg=0; *args[arg+1]; arg++)
6288 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006289 *tmp = '\0'; // fix the next arg to \0
6290 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006291 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006292 else if (!strcmp(args[0], "default")) {
6293 kwm = KWM_DEF;
6294 for (arg=0; *args[arg+1]; arg++)
6295 args[arg] = args[arg+1]; // shift args after inversion
6296 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006297
William Lallemand0f99e342011-10-12 17:50:54 +02006298 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6299 strcmp(args[0], "log") != 0) {
6300 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006301 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006302 }
6303
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006304 /* detect section start */
6305 list_for_each_entry(ics, &sections, list) {
6306 if (strcmp(args[0], ics->section_name) == 0) {
6307 cursection = ics->section_name;
6308 cs = ics;
6309 break;
6310 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006311 }
6312
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006314 if (cs)
6315 err_code |= cs->section_parser(file, linenum, args, kwm);
6316 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006317 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006318 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006320
6321 if (err_code & ERR_ABORT)
6322 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006324 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006325 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006326 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006327}
6328
Willy Tarreau64ab6072014-09-16 12:17:36 +02006329/* This function propagates processes from frontend <from> to backend <to> so
6330 * that it is always guaranteed that a backend pointed to by a frontend is
6331 * bound to all of its processes. After that, if the target is a "listen"
6332 * instance, the function recursively descends the target's own targets along
6333 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6334 * checked first to ensure that <to> is already bound to all processes of
6335 * <from>, there is no risk of looping and we ensure to follow the shortest
6336 * path to the destination.
6337 *
6338 * It is possible to set <to> to NULL for the first call so that the function
6339 * takes care of visiting the initial frontend in <from>.
6340 *
6341 * It is important to note that the function relies on the fact that all names
6342 * have already been resolved.
6343 */
6344void propagate_processes(struct proxy *from, struct proxy *to)
6345{
6346 struct switching_rule *rule;
6347 struct hdr_exp *exp;
6348
6349 if (to) {
6350 /* check whether we need to go down */
6351 if (from->bind_proc &&
6352 (from->bind_proc & to->bind_proc) == from->bind_proc)
6353 return;
6354
6355 if (!from->bind_proc && !to->bind_proc)
6356 return;
6357
6358 to->bind_proc = from->bind_proc ?
6359 (to->bind_proc | from->bind_proc) : 0;
6360
6361 /* now propagate down */
6362 from = to;
6363 }
6364
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006365 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006366 return;
6367
Willy Tarreauf6b70012014-12-18 14:00:43 +01006368 if (from->state == PR_STSTOPPED)
6369 return;
6370
Willy Tarreau64ab6072014-09-16 12:17:36 +02006371 /* default_backend */
6372 if (from->defbe.be)
6373 propagate_processes(from, from->defbe.be);
6374
6375 /* use_backend */
6376 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006377 if (rule->dynamic)
6378 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006379 to = rule->be.backend;
6380 propagate_processes(from, to);
6381 }
6382
6383 /* reqsetbe */
6384 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6385 if (exp->action != ACT_SETBE)
6386 continue;
6387 to = (struct proxy *)exp->replace;
6388 propagate_processes(from, to);
6389 }
6390}
6391
Willy Tarreaubb925012009-07-23 13:36:36 +02006392/*
6393 * Returns the error code, 0 if OK, or any combination of :
6394 * - ERR_ABORT: must abort ASAP
6395 * - ERR_FATAL: we can continue parsing but not start the service
6396 * - ERR_WARN: a warning has been emitted
6397 * - ERR_ALERT: an alert has been emitted
6398 * Only the two first ones can stop processing, the two others are just
6399 * indicators.
6400 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006401int check_config_validity()
6402{
6403 int cfgerr = 0;
6404 struct proxy *curproxy = NULL;
6405 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006406 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006407 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006408 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006410 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 /*
6412 * Now, check for the integrity of all that we have collected.
6413 */
6414
6415 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006416 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417
Willy Tarreau193b8c62012-11-22 00:17:38 +01006418 if (!global.tune.max_http_hdr)
6419 global.tune.max_http_hdr = MAX_HTTP_HDR;
6420
6421 if (!global.tune.cookie_len)
6422 global.tune.cookie_len = CAPTURE_LEN;
6423
6424 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6425
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006426 /* Post initialisation of the users and groups lists. */
6427 err_code = userlist_postinit();
6428 if (err_code != ERR_NONE)
6429 goto out;
6430
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006431 /* first, we will invert the proxy list order */
6432 curproxy = NULL;
6433 while (proxy) {
6434 struct proxy *next;
6435
6436 next = proxy->next;
6437 proxy->next = curproxy;
6438 curproxy = proxy;
6439 if (!next)
6440 break;
6441 proxy = next;
6442 }
6443
Willy Tarreau419ead82014-09-16 13:41:21 +02006444 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006445 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006446 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006447 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006448 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006449 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006450 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006451 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006452
Willy Tarreau050536d2012-10-04 08:47:34 +02006453 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006454 /* proxy ID not set, use automatic numbering with first
6455 * spare entry starting with next_pxid.
6456 */
6457 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6458 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6459 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006460 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006461 next_pxid++;
6462
Willy Tarreau55ea7572007-06-17 19:56:27 +02006463
Willy Tarreaubaaee002006-06-26 02:48:02 +02006464 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006465 /* ensure we don't keep listeners uselessly bound */
6466 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 continue;
6468 }
6469
Willy Tarreau102df612014-05-07 23:56:38 +02006470 /* Check multi-process mode compatibility for the current proxy */
6471
6472 if (curproxy->bind_proc) {
6473 /* an explicit bind-process was specified, let's check how many
6474 * processes remain.
6475 */
6476 nbproc = popcount(curproxy->bind_proc);
6477
6478 curproxy->bind_proc &= nbits(global.nbproc);
6479 if (!curproxy->bind_proc && nbproc == 1) {
6480 Warning("Proxy '%s': the process specified on the 'bind-process' directive refers to a process number that is higher than global.nbproc. The proxy has been forced to run on process 1 only.\n", curproxy->id);
6481 curproxy->bind_proc = 1;
6482 }
6483 else if (!curproxy->bind_proc && nbproc > 1) {
6484 Warning("Proxy '%s': all processes specified on the 'bind-process' directive refer to numbers that are all higher than global.nbproc. The directive was ignored and the proxy will run on all processes.\n", curproxy->id);
6485 curproxy->bind_proc = 0;
6486 }
6487 }
6488
Willy Tarreau3d209582014-05-09 17:06:11 +02006489 /* check and reduce the bind-proc of each listener */
6490 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6491 unsigned long mask;
6492
6493 if (!bind_conf->bind_proc)
6494 continue;
6495
6496 mask = nbits(global.nbproc);
6497 if (curproxy->bind_proc)
6498 mask &= curproxy->bind_proc;
6499 /* mask cannot be null here thanks to the previous checks */
6500
6501 nbproc = popcount(bind_conf->bind_proc);
6502 bind_conf->bind_proc &= mask;
6503
6504 if (!bind_conf->bind_proc && nbproc == 1) {
6505 Warning("Proxy '%s': the process number specified on the 'process' directive of 'bind %s' at [%s:%d] refers to a process not covered by the proxy. This has been fixed by forcing it to run on the proxy's first process only.\n",
6506 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6507 bind_conf->bind_proc = mask & ~(mask - 1);
6508 }
6509 else if (!bind_conf->bind_proc && nbproc > 1) {
6510 Warning("Proxy '%s': the process range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to processes not covered by the proxy. The directive was ignored so that all of the proxy's processes are used.\n",
6511 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6512 bind_conf->bind_proc = 0;
6513 }
6514 }
6515
Willy Tarreau102df612014-05-07 23:56:38 +02006516 if (global.nbproc > 1 && curproxy->table.peers.name) {
6517 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6518 curproxy->id);
6519 cfgerr++;
6520 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006521
Willy Tarreauff01a212009-03-15 13:46:16 +01006522 switch (curproxy->mode) {
6523 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006524 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006525 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006526 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6527 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006528 cfgerr++;
6529 }
6530
6531 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006532 Warning("config : servers will be ignored for %s '%s'.\n",
6533 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006534 break;
6535
6536 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006537 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006538 break;
6539
6540 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006541 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006542 break;
6543 }
6544
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006545 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006546 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006547 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006548 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6549 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006550 cfgerr++;
6551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006553 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006554 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6555 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006556 cfgerr++;
6557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006558#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006559 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006560 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6561 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006562 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006563 }
6564 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006565 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006566 /* If no LB algo is set in a backend, and we're not in
6567 * transparent mode, dispatch mode nor proxy mode, we
6568 * want to use balance roundrobin by default.
6569 */
6570 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6571 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 }
6573 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006574
Willy Tarreau1620ec32011-08-06 17:05:02 +02006575 if (curproxy->options & PR_O_DISPATCH)
6576 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6577 else if (curproxy->options & PR_O_HTTP_PROXY)
6578 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6579 else if (curproxy->options & PR_O_TRANSP)
6580 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006581
Willy Tarreau1620ec32011-08-06 17:05:02 +02006582 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6583 if (curproxy->options & PR_O_DISABLE404) {
6584 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6585 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6586 err_code |= ERR_WARN;
6587 curproxy->options &= ~PR_O_DISABLE404;
6588 }
6589 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6590 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6591 "send-state", proxy_type_str(curproxy), curproxy->id);
6592 err_code |= ERR_WARN;
6593 curproxy->options &= ~PR_O2_CHK_SNDST;
6594 }
Willy Tarreauef781042010-01-27 11:53:01 +01006595 }
6596
Simon Horman98637e52014-06-20 12:30:16 +09006597 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6598 if (!global.external_check) {
6599 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6600 curproxy->id, "option external-check");
6601 cfgerr++;
6602 }
6603 if (!curproxy->check_command) {
6604 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6605 curproxy->id, "option external-check");
6606 cfgerr++;
6607 }
6608 }
6609
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006610 if ((curproxy->email_alert.mailers.name || curproxy->email_alert.from ||
6611 curproxy->email_alert.myhostname || curproxy->email_alert.to)) {
6612 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6613 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
6614 "'email-alert from', 'email-alert mailer', 'email-alert hostname' or 'email-alert to' "
6615 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6616 "to be present).\n",
6617 proxy_type_str(curproxy), curproxy->id);
6618 err_code |= ERR_WARN;
6619 free_email_alert(curproxy);
6620 }
6621 if (!curproxy->email_alert.myhostname)
6622 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006623 }
6624
Simon Horman98637e52014-06-20 12:30:16 +09006625 if (curproxy->check_command) {
6626 int clear = 0;
6627 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6628 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6629 "external-check command", proxy_type_str(curproxy), curproxy->id);
6630 err_code |= ERR_WARN;
6631 clear = 1;
6632 }
6633 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6634 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6635 curproxy->id, "external-check command");
6636 cfgerr++;
6637 }
6638 if (clear) {
6639 free(curproxy->check_command);
6640 curproxy->check_command = NULL;
6641 }
6642 }
6643
6644 if (curproxy->check_path) {
6645 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6646 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6647 "external-check path", proxy_type_str(curproxy), curproxy->id);
6648 err_code |= ERR_WARN;
6649 free(curproxy->check_path);
6650 curproxy->check_path = NULL;
6651 }
6652 }
6653
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006654 /* if a default backend was specified, let's find it */
6655 if (curproxy->defbe.name) {
6656 struct proxy *target;
6657
Alex Williams96532db2009-11-01 21:27:13 -05006658 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006659 if (!target) {
6660 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6661 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006662 cfgerr++;
6663 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006664 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6665 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006666 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006667 } else {
6668 free(curproxy->defbe.name);
6669 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006670
6671 /* Emit a warning if this proxy also has some servers */
6672 if (curproxy->srv) {
6673 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6674 curproxy->id);
6675 err_code |= ERR_WARN;
6676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006677 }
6678 }
6679
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006680 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006681 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6682 /* map jump target for ACT_SETBE in req_rep chain */
6683 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006684 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006685 struct proxy *target;
6686
Willy Tarreaua496b602006-12-17 23:15:24 +01006687 if (exp->action != ACT_SETBE)
6688 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006689
Alex Williams96532db2009-11-01 21:27:13 -05006690 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006691 if (!target) {
6692 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6693 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006694 cfgerr++;
6695 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006696 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6697 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006698 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006699 } else {
6700 free((void *)exp->replace);
6701 exp->replace = (const char *)target;
6702 }
6703 }
6704 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006705
6706 /* find the target proxy for 'use_backend' rules */
6707 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006708 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006709 struct logformat_node *node;
6710 char *pxname;
6711
6712 /* Try to parse the string as a log format expression. If the result
6713 * of the parsing is only one entry containing a simple string, then
6714 * it's a standard string corresponding to a static rule, thus the
6715 * parsing is cancelled and be.name is restored to be resolved.
6716 */
6717 pxname = rule->be.name;
6718 LIST_INIT(&rule->be.expr);
6719 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6720 curproxy->conf.args.file, curproxy->conf.args.line);
6721 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6722
6723 if (!LIST_ISEMPTY(&rule->be.expr)) {
6724 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6725 rule->dynamic = 1;
6726 free(pxname);
6727 continue;
6728 }
6729 /* simple string: free the expression and fall back to static rule */
6730 free(node->arg);
6731 free(node);
6732 }
6733
6734 rule->dynamic = 0;
6735 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006736
Alex Williams96532db2009-11-01 21:27:13 -05006737 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006738
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006739 if (!target) {
6740 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6741 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006742 cfgerr++;
6743 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006744 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6745 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006746 cfgerr++;
6747 } else {
6748 free((void *)rule->be.name);
6749 rule->be.backend = target;
6750 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006751 }
6752
Willy Tarreau64ab6072014-09-16 12:17:36 +02006753 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006754 list_for_each_entry(srule, &curproxy->server_rules, list) {
6755 struct server *target = findserver(curproxy, srule->srv.name);
6756
6757 if (!target) {
6758 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6759 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6760 cfgerr++;
6761 continue;
6762 }
6763 free((void *)srule->srv.name);
6764 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006765 }
6766
Emeric Brunb982a3d2010-01-04 15:45:53 +01006767 /* find the target table for 'stick' rules */
6768 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6769 struct proxy *target;
6770
Emeric Brun1d33b292010-01-04 15:47:17 +01006771 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6772 if (mrule->flags & STK_IS_STORE)
6773 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6774
Emeric Brunb982a3d2010-01-04 15:45:53 +01006775 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006776 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006777 else
6778 target = curproxy;
6779
6780 if (!target) {
6781 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6782 curproxy->id, mrule->table.name);
6783 cfgerr++;
6784 }
6785 else if (target->table.size == 0) {
6786 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6787 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6788 cfgerr++;
6789 }
Willy Tarreau12785782012-04-27 21:37:17 +02006790 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6791 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006792 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6793 cfgerr++;
6794 }
6795 else {
6796 free((void *)mrule->table.name);
6797 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006798 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006799 }
6800 }
6801
6802 /* find the target table for 'store response' rules */
6803 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6804 struct proxy *target;
6805
Emeric Brun1d33b292010-01-04 15:47:17 +01006806 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6807
Emeric Brunb982a3d2010-01-04 15:45:53 +01006808 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006809 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006810 else
6811 target = curproxy;
6812
6813 if (!target) {
6814 Alert("Proxy '%s': unable to find store table '%s'.\n",
6815 curproxy->id, mrule->table.name);
6816 cfgerr++;
6817 }
6818 else if (target->table.size == 0) {
6819 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6820 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6821 cfgerr++;
6822 }
Willy Tarreau12785782012-04-27 21:37:17 +02006823 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6824 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006825 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6826 cfgerr++;
6827 }
6828 else {
6829 free((void *)mrule->table.name);
6830 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006831 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006832 }
6833 }
6834
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006835 /* find the target table for 'tcp-request' layer 4 rules */
6836 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6837 struct proxy *target;
6838
Willy Tarreaub4c84932013-07-23 19:15:30 +02006839 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006840 continue;
6841
6842 if (trule->act_prm.trk_ctr.table.n)
6843 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6844 else
6845 target = curproxy;
6846
6847 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006848 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6849 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006850 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006851 cfgerr++;
6852 }
6853 else if (target->table.size == 0) {
6854 Alert("Proxy '%s': table '%s' used but not configured.\n",
6855 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6856 cfgerr++;
6857 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006858 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6859 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6860 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 +01006861 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006862 cfgerr++;
6863 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006864 else {
6865 free(trule->act_prm.trk_ctr.table.n);
6866 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006867 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006868 * to pass a list of counters to track and allocate them right here using
6869 * stktable_alloc_data_type().
6870 */
6871 }
6872 }
6873
Willy Tarreaud1f96522010-08-03 19:34:32 +02006874 /* find the target table for 'tcp-request' layer 6 rules */
6875 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6876 struct proxy *target;
6877
Willy Tarreaub4c84932013-07-23 19:15:30 +02006878 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006879 continue;
6880
6881 if (trule->act_prm.trk_ctr.table.n)
6882 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6883 else
6884 target = curproxy;
6885
6886 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006887 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6888 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006889 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006890 cfgerr++;
6891 }
6892 else if (target->table.size == 0) {
6893 Alert("Proxy '%s': table '%s' used but not configured.\n",
6894 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6895 cfgerr++;
6896 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006897 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6898 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6899 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 +01006900 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006901 cfgerr++;
6902 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006903 else {
6904 free(trule->act_prm.trk_ctr.table.n);
6905 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006906 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006907 * to pass a list of counters to track and allocate them right here using
6908 * stktable_alloc_data_type().
6909 */
6910 }
6911 }
6912
Willy Tarreau09448f72014-06-25 18:12:15 +02006913 /* find the target table for 'http-request' layer 7 rules */
6914 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6915 struct proxy *target;
6916
6917 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6918 continue;
6919
6920 if (hrqrule->act_prm.trk_ctr.table.n)
6921 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6922 else
6923 target = curproxy;
6924
6925 if (!target) {
6926 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6927 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6928 http_req_trk_idx(hrqrule->action));
6929 cfgerr++;
6930 }
6931 else if (target->table.size == 0) {
6932 Alert("Proxy '%s': table '%s' used but not configured.\n",
6933 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6934 cfgerr++;
6935 }
6936 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6937 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6938 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6939 http_req_trk_idx(hrqrule->action));
6940 cfgerr++;
6941 }
6942 else {
6943 free(hrqrule->act_prm.trk_ctr.table.n);
6944 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6945 /* Note: if we decide to enhance the track-sc syntax, we may be able
6946 * to pass a list of counters to track and allocate them right here using
6947 * stktable_alloc_data_type().
6948 */
6949 }
6950 }
6951
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006952 /* move any "block" rules at the beginning of the http-request rules */
6953 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6954 /* insert block_rules into http_req_rules at the beginning */
6955 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6956 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6957 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6958 curproxy->http_req_rules.n = curproxy->block_rules.n;
6959 LIST_INIT(&curproxy->block_rules);
6960 }
6961
Emeric Brun32da3c42010-09-23 18:39:19 +02006962 if (curproxy->table.peers.name) {
6963 struct peers *curpeers = peers;
6964
6965 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6966 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6967 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006968 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006969 break;
6970 }
6971 }
6972
6973 if (!curpeers) {
6974 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6975 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006976 free((void *)curproxy->table.peers.name);
6977 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006978 cfgerr++;
6979 }
6980 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006981 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6982 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006983 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006984 cfgerr++;
6985 }
6986 }
6987
Simon Horman9dc49962015-01-30 11:22:59 +09006988
6989 if (curproxy->email_alert.mailers.name) {
6990 struct mailers *curmailers = mailers;
6991
6992 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
6993 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
6994 free(curproxy->email_alert.mailers.name);
6995 curproxy->email_alert.mailers.m = curmailers;
6996 curmailers->users++;
6997 break;
6998 }
6999 }
7000
7001 if (!curmailers) {
7002 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7003 curproxy->id, curproxy->email_alert.mailers.name);
7004 free_email_alert(curproxy);
7005 cfgerr++;
7006 }
7007 }
7008
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007009 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007010 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007011 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7012 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7013 "proxy", curproxy->id);
7014 cfgerr++;
7015 goto out_uri_auth_compat;
7016 }
7017
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007018 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007019 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007020 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007021 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007022
Willy Tarreau95fa4692010-02-01 13:05:50 +01007023 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7024 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007025
7026 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007027 uri_auth_compat_req[i++] = "realm";
7028 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7029 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007030
Willy Tarreau95fa4692010-02-01 13:05:50 +01007031 uri_auth_compat_req[i++] = "unless";
7032 uri_auth_compat_req[i++] = "{";
7033 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7034 uri_auth_compat_req[i++] = "}";
7035 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007036
Willy Tarreauff011f22011-01-06 17:51:27 +01007037 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7038 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007039 cfgerr++;
7040 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007041 }
7042
Willy Tarreauff011f22011-01-06 17:51:27 +01007043 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007044
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007045 if (curproxy->uri_auth->auth_realm) {
7046 free(curproxy->uri_auth->auth_realm);
7047 curproxy->uri_auth->auth_realm = NULL;
7048 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007049
7050 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007051 }
7052out_uri_auth_compat:
7053
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007054 /* compile the log format */
7055 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007056 if (curproxy->conf.logformat_string != default_http_log_format &&
7057 curproxy->conf.logformat_string != default_tcp_log_format &&
7058 curproxy->conf.logformat_string != clf_http_log_format)
7059 free(curproxy->conf.logformat_string);
7060 curproxy->conf.logformat_string = NULL;
7061 free(curproxy->conf.lfs_file);
7062 curproxy->conf.lfs_file = NULL;
7063 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007064 }
7065
Willy Tarreau62a61232013-04-12 18:13:46 +02007066 if (curproxy->conf.logformat_string) {
7067 curproxy->conf.args.ctx = ARGC_LOG;
7068 curproxy->conf.args.file = curproxy->conf.lfs_file;
7069 curproxy->conf.args.line = curproxy->conf.lfs_line;
7070 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007071 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007072 curproxy->conf.args.file = NULL;
7073 curproxy->conf.args.line = 0;
7074 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007075
Willy Tarreau62a61232013-04-12 18:13:46 +02007076 if (curproxy->conf.uniqueid_format_string) {
7077 curproxy->conf.args.ctx = ARGC_UIF;
7078 curproxy->conf.args.file = curproxy->conf.uif_file;
7079 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007080 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007081 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007082 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007083 curproxy->conf.args.file = NULL;
7084 curproxy->conf.args.line = 0;
7085 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007086
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007087 /* only now we can check if some args remain unresolved.
7088 * This must be done after the users and groups resolution.
7089 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007090 cfgerr += smp_resolve_args(curproxy);
7091 if (!cfgerr)
7092 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007093
Willy Tarreau2738a142006-07-08 17:28:09 +02007094 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007095 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007096 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007097 (!curproxy->timeout.connect ||
7098 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007099 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007100 " | While not properly invalid, you will certainly encounter various problems\n"
7101 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007102 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007103 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007104 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007105 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007106
Willy Tarreau1fa31262007-12-03 00:36:16 +01007107 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7108 * We must still support older configurations, so let's find out whether those
7109 * parameters have been set or must be copied from contimeouts.
7110 */
7111 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007112 if (!curproxy->timeout.tarpit ||
7113 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007114 /* tarpit timeout not set. We search in the following order:
7115 * default.tarpit, curr.connect, default.connect.
7116 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007117 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007118 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007119 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007120 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007121 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007122 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007123 }
7124 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007125 (!curproxy->timeout.queue ||
7126 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007127 /* queue timeout not set. We search in the following order:
7128 * default.queue, curr.connect, default.connect.
7129 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007130 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007131 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007132 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007133 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007134 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007135 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007136 }
7137 }
7138
Willy Tarreau1620ec32011-08-06 17:05:02 +02007139 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007140 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7141 curproxy->check_req = (char *)malloc(curproxy->check_len);
7142 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007143 }
7144
Willy Tarreau215663d2014-06-13 18:30:23 +02007145 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7146 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7147 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7148 proxy_type_str(curproxy), curproxy->id);
7149 err_code |= ERR_WARN;
7150 }
7151
Willy Tarreau193b8c62012-11-22 00:17:38 +01007152 /* ensure that cookie capture length is not too large */
7153 if (curproxy->capture_len >= global.tune.cookie_len) {
7154 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7155 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7156 err_code |= ERR_WARN;
7157 curproxy->capture_len = global.tune.cookie_len - 1;
7158 }
7159
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007160 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007161 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007162 curproxy->req_cap_pool = create_pool("ptrcap",
7163 curproxy->nb_req_cap * sizeof(char *),
7164 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007165 }
7166
7167 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007168 curproxy->rsp_cap_pool = create_pool("ptrcap",
7169 curproxy->nb_rsp_cap * sizeof(char *),
7170 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007171 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007172
Willy Tarreaubaaee002006-06-26 02:48:02 +02007173 /* first, we will invert the servers list order */
7174 newsrv = NULL;
7175 while (curproxy->srv) {
7176 struct server *next;
7177
7178 next = curproxy->srv->next;
7179 curproxy->srv->next = newsrv;
7180 newsrv = curproxy->srv;
7181 if (!next)
7182 break;
7183 curproxy->srv = next;
7184 }
7185
Willy Tarreau17edc812014-01-03 12:14:34 +01007186 /* Check that no server name conflicts. This causes trouble in the stats.
7187 * We only emit a warning for the first conflict affecting each server,
7188 * in order to avoid combinatory explosion if all servers have the same
7189 * name. We do that only for servers which do not have an explicit ID,
7190 * because these IDs were made also for distinguishing them and we don't
7191 * want to annoy people who correctly manage them.
7192 */
7193 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7194 struct server *other_srv;
7195
7196 if (newsrv->puid)
7197 continue;
7198
7199 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7200 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7201 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7202 newsrv->conf.file, newsrv->conf.line,
7203 proxy_type_str(curproxy), curproxy->id,
7204 newsrv->id, other_srv->conf.line);
7205 break;
7206 }
7207 }
7208 }
7209
Willy Tarreaudd701652010-05-25 23:03:02 +02007210 /* assign automatic UIDs to servers which don't have one yet */
7211 next_id = 1;
7212 newsrv = curproxy->srv;
7213 while (newsrv != NULL) {
7214 if (!newsrv->puid) {
7215 /* server ID not set, use automatic numbering with first
7216 * spare entry starting with next_svid.
7217 */
7218 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7219 newsrv->conf.id.key = newsrv->puid = next_id;
7220 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7221 }
7222 next_id++;
7223 newsrv = newsrv->next;
7224 }
7225
Willy Tarreau20697042007-11-15 23:26:18 +01007226 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007227 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007228
Willy Tarreau62c3be22012-01-20 13:12:32 +01007229 /*
7230 * If this server supports a maxconn parameter, it needs a dedicated
7231 * tasks to fill the emptied slots when a connection leaves.
7232 * Also, resolve deferred tracking dependency if needed.
7233 */
7234 newsrv = curproxy->srv;
7235 while (newsrv != NULL) {
7236 if (newsrv->minconn > newsrv->maxconn) {
7237 /* Only 'minconn' was specified, or it was higher than or equal
7238 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7239 * this will avoid further useless expensive computations.
7240 */
7241 newsrv->maxconn = newsrv->minconn;
7242 } else if (newsrv->maxconn && !newsrv->minconn) {
7243 /* minconn was not specified, so we set it to maxconn */
7244 newsrv->minconn = newsrv->maxconn;
7245 }
7246
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007247#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007248 if (newsrv->use_ssl || newsrv->check.use_ssl)
7249 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007250#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007251
Willy Tarreau2f075e92013-12-03 11:11:34 +01007252 /* set the check type on the server */
7253 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7254
Willy Tarreau62c3be22012-01-20 13:12:32 +01007255 if (newsrv->trackit) {
7256 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007257 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007258 char *pname, *sname;
7259
7260 pname = newsrv->trackit;
7261 sname = strrchr(pname, '/');
7262
7263 if (sname)
7264 *sname++ = '\0';
7265 else {
7266 sname = pname;
7267 pname = NULL;
7268 }
7269
7270 if (pname) {
7271 px = findproxy(pname, PR_CAP_BE);
7272 if (!px) {
7273 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7274 proxy_type_str(curproxy), curproxy->id,
7275 newsrv->id, pname);
7276 cfgerr++;
7277 goto next_srv;
7278 }
7279 } else
7280 px = curproxy;
7281
7282 srv = findserver(px, sname);
7283 if (!srv) {
7284 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7285 proxy_type_str(curproxy), curproxy->id,
7286 newsrv->id, sname);
7287 cfgerr++;
7288 goto next_srv;
7289 }
7290
Willy Tarreau32091232014-05-16 13:52:00 +02007291 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7292 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7293 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007294 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007295 "tracking as it does not have any check nor agent enabled.\n",
7296 proxy_type_str(curproxy), curproxy->id,
7297 newsrv->id, px->id, srv->id);
7298 cfgerr++;
7299 goto next_srv;
7300 }
7301
7302 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7303
7304 if (loop) {
7305 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7306 "belongs to a tracking chain looping back to %s/%s.\n",
7307 proxy_type_str(curproxy), curproxy->id,
7308 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007309 cfgerr++;
7310 goto next_srv;
7311 }
7312
7313 if (curproxy != px &&
7314 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7315 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7316 "tracking: disable-on-404 option inconsistency.\n",
7317 proxy_type_str(curproxy), curproxy->id,
7318 newsrv->id, px->id, srv->id);
7319 cfgerr++;
7320 goto next_srv;
7321 }
7322
7323 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007324 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007325 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007326 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007327 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007328 }
7329
7330 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007331 newsrv->tracknext = srv->trackers;
7332 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007333
7334 free(newsrv->trackit);
7335 newsrv->trackit = NULL;
7336 }
7337 next_srv:
7338 newsrv = newsrv->next;
7339 }
7340
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007341 /* We have to initialize the server lookup mechanism depending
7342 * on what LB algorithm was choosen.
7343 */
7344
7345 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7346 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7347 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007348 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7349 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7350 init_server_map(curproxy);
7351 } else {
7352 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7353 fwrr_init_server_groups(curproxy);
7354 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007355 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007356
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007357 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007358 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7359 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7360 fwlc_init_server_tree(curproxy);
7361 } else {
7362 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7363 fas_init_server_tree(curproxy);
7364 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007365 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007366
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007367 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007368 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7369 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7370 chash_init_server_tree(curproxy);
7371 } else {
7372 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7373 init_server_map(curproxy);
7374 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007375 break;
7376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007377
7378 if (curproxy->options & PR_O_LOGASAP)
7379 curproxy->to_log &= ~LW_BYTES;
7380
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007381 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007382 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007383 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7384 proxy_type_str(curproxy), curproxy->id);
7385 err_code |= ERR_WARN;
7386 }
7387
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007388 if (curproxy->mode != PR_MODE_HTTP) {
7389 int optnum;
7390
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007391 if (curproxy->uri_auth) {
7392 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7393 proxy_type_str(curproxy), curproxy->id);
7394 err_code |= ERR_WARN;
7395 curproxy->uri_auth = NULL;
7396 }
7397
Willy Tarreau87cf5142011-08-19 22:57:24 +02007398 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007399 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7400 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7401 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007402 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007403 }
7404
7405 if (curproxy->options & PR_O_ORGTO) {
7406 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7407 "originalto", proxy_type_str(curproxy), curproxy->id);
7408 err_code |= ERR_WARN;
7409 curproxy->options &= ~PR_O_ORGTO;
7410 }
7411
7412 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7413 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7414 (curproxy->cap & cfg_opts[optnum].cap) &&
7415 (curproxy->options & cfg_opts[optnum].val)) {
7416 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7417 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7418 err_code |= ERR_WARN;
7419 curproxy->options &= ~cfg_opts[optnum].val;
7420 }
7421 }
7422
7423 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7424 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7425 (curproxy->cap & cfg_opts2[optnum].cap) &&
7426 (curproxy->options2 & cfg_opts2[optnum].val)) {
7427 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7428 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7429 err_code |= ERR_WARN;
7430 curproxy->options2 &= ~cfg_opts2[optnum].val;
7431 }
7432 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007433
Pieter Baauwd551fb52013-05-08 22:49:23 +02007434#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007435 if (curproxy->conn_src.bind_hdr_occ) {
7436 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007437 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007438 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007439 err_code |= ERR_WARN;
7440 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007441#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007442 }
7443
Willy Tarreaubaaee002006-06-26 02:48:02 +02007444 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007445 * ensure that we're not cross-dressing a TCP server into HTTP.
7446 */
7447 newsrv = curproxy->srv;
7448 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007449 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007450 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7451 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007452 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007453 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007454
Willy Tarreau0cec3312011-10-31 13:49:26 +01007455 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7456 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7457 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7458 err_code |= ERR_WARN;
7459 }
7460
Willy Tarreauc93cd162014-05-13 15:54:22 +02007461 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007462 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7463 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7464 err_code |= ERR_WARN;
7465 }
7466
Pieter Baauwd551fb52013-05-08 22:49:23 +02007467#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007468 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7469 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007470 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 +01007471 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007472 err_code |= ERR_WARN;
7473 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007474#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007475 newsrv = newsrv->next;
7476 }
7477
Willy Tarreaue42bd962014-09-16 16:21:19 +02007478 /* check if we have a frontend with "tcp-request content" looking at L7
7479 * with no inspect-delay
7480 */
7481 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7482 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7483 if (trule->action == TCP_ACT_CAPTURE &&
7484 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7485 break;
7486 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7487 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7488 break;
7489 }
7490
7491 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7492 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7493 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7494 " This means that these rules will randomly find their contents. This can be fixed by"
7495 " setting the tcp-request inspect-delay.\n",
7496 proxy_type_str(curproxy), curproxy->id);
7497 err_code |= ERR_WARN;
7498 }
7499 }
7500
Willy Tarreauc1a21672009-08-16 22:37:44 +02007501 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007502 if (!curproxy->accept)
7503 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007504
Willy Tarreauc1a21672009-08-16 22:37:44 +02007505 if (curproxy->tcp_req.inspect_delay ||
7506 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007507 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007508
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007509 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007510 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007511 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007512 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007513
7514 /* both TCP and HTTP must check switching rules */
7515 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7516 }
7517
7518 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007519 if (curproxy->tcp_req.inspect_delay ||
7520 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7521 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7522
Emeric Brun97679e72010-09-23 17:56:44 +02007523 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7524 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7525
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007526 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007527 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007528 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007529 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007530
7531 /* If the backend does requires RDP cookie persistence, we have to
7532 * enable the corresponding analyser.
7533 */
7534 if (curproxy->options2 & PR_O2_RDPC_PRST)
7535 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7536 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007537 }
7538
7539 /***********************************************************/
7540 /* At this point, target names have already been resolved. */
7541 /***********************************************************/
7542
7543 /* Check multi-process mode compatibility */
7544
7545 if (global.nbproc > 1 && global.stats_fe) {
7546 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7547 unsigned long mask;
7548
7549 mask = nbits(global.nbproc);
7550 if (global.stats_fe->bind_proc)
7551 mask &= global.stats_fe->bind_proc;
7552
7553 if (bind_conf->bind_proc)
7554 mask &= bind_conf->bind_proc;
7555
7556 /* stop here if more than one process is used */
7557 if (popcount(mask) > 1)
7558 break;
7559 }
7560 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7561 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding globally using 'stats bind-process' or per socket using the 'process' attribute.\n");
7562 }
7563 }
7564
7565 /* Make each frontend inherit bind-process from its listeners when not specified. */
7566 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7567 if (curproxy->bind_proc)
7568 continue;
7569
7570 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7571 unsigned long mask;
7572
7573 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7574 curproxy->bind_proc |= mask;
7575 }
7576
7577 if (!curproxy->bind_proc)
7578 curproxy->bind_proc = ~0UL;
7579 }
7580
7581 if (global.stats_fe) {
7582 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7583 unsigned long mask;
7584
7585 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7586 global.stats_fe->bind_proc |= mask;
7587 }
7588 if (!global.stats_fe->bind_proc)
7589 global.stats_fe->bind_proc = ~0UL;
7590 }
7591
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007592 /* propagate bindings from frontends to backends. Don't do it if there
7593 * are any fatal errors as we must not call it with unresolved proxies.
7594 */
7595 if (!cfgerr) {
7596 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7597 if (curproxy->cap & PR_CAP_FE)
7598 propagate_processes(curproxy, NULL);
7599 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007600 }
7601
7602 /* Bind each unbound backend to all processes when not specified. */
7603 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7604 if (curproxy->bind_proc)
7605 continue;
7606 curproxy->bind_proc = ~0UL;
7607 }
7608
7609 /*******************************************************/
7610 /* At this step, all proxies have a non-null bind_proc */
7611 /*******************************************************/
7612
7613 /* perform the final checks before creating tasks */
7614
7615 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7616 struct listener *listener;
7617 unsigned int next_id;
7618 int nbproc;
7619
7620 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007621
Emeric Brunc52962f2012-11-15 18:28:02 +01007622#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007623 /* Configure SSL for each bind line.
7624 * Note: if configuration fails at some point, the ->ctx member
7625 * remains NULL so that listeners can later detach.
7626 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007627 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007628 int alloc_ctx;
7629
Emeric Brunc52962f2012-11-15 18:28:02 +01007630 if (!bind_conf->is_ssl) {
7631 if (bind_conf->default_ctx) {
7632 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7633 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7634 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007635 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007636 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007637 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007638 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007639 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007640 cfgerr++;
7641 continue;
7642 }
7643
Emeric Brun8dc60392014-05-09 13:52:00 +02007644 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007645 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007646 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7647 Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
7648 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007649 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007650 cfgerr++;
7651 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007652 }
7653
Emeric Brunfc0421f2012-09-07 17:30:07 +02007654 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007655 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007656 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007657#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007658
Willy Tarreaue6b98942007-10-29 01:09:36 +01007659 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007660 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007661 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007662 if (!listener->luid) {
7663 /* listener ID not set, use automatic numbering with first
7664 * spare entry starting with next_luid.
7665 */
7666 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7667 listener->conf.id.key = listener->luid = next_id;
7668 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007669 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007670 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007671
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007672 /* enable separate counters */
7673 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7674 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007675 if (!listener->name)
7676 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007677 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007678
Willy Tarreaue6b98942007-10-29 01:09:36 +01007679 if (curproxy->options & PR_O_TCP_NOLING)
7680 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007681 if (!listener->maxconn)
7682 listener->maxconn = curproxy->maxconn;
7683 if (!listener->backlog)
7684 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007685 if (!listener->maxaccept)
7686 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7687
7688 /* we want to have an optimal behaviour on single process mode to
7689 * maximize the work at once, but in multi-process we want to keep
7690 * some fairness between processes, so we target half of the max
7691 * number of events to be balanced over all the processes the proxy
7692 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7693 * used to disable the limit.
7694 */
7695 if (listener->maxaccept > 0) {
7696 if (nbproc > 1)
7697 listener->maxaccept = (listener->maxaccept + 1) / 2;
7698 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7699 }
7700
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007701 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007702 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007703 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007704 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007705
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007706 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7707 listener->options |= LI_O_TCP_RULES;
7708
Willy Tarreaude3041d2010-05-31 10:56:17 +02007709 if (curproxy->mon_mask.s_addr)
7710 listener->options |= LI_O_CHK_MONNET;
7711
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007712 /* smart accept mode is automatic in HTTP mode */
7713 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007714 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007715 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7716 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007717 }
7718
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007719 /* Release unused SSL configs */
7720 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7721 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007722 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007723#ifdef USE_OPENSSL
7724 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007725 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007726 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007727 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007728 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007729#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007730 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007731
Willy Tarreau102df612014-05-07 23:56:38 +02007732 if (nbproc > 1) {
7733 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007734 int count, maxproc = 0;
7735
7736 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7737 count = popcount(bind_conf->bind_proc);
7738 if (count > maxproc)
7739 maxproc = count;
7740 }
7741 /* backends have 0, frontends have 1 or more */
7742 if (maxproc != 1)
7743 Warning("Proxy '%s': in multi-process mode, stats will be"
7744 " limited to process assigned to the current request.\n",
7745 curproxy->id);
7746
Willy Tarreau102df612014-05-07 23:56:38 +02007747 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7748 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7749 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007750 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007751 }
Willy Tarreau102df612014-05-07 23:56:38 +02007752 if (curproxy->appsession_name) {
7753 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7754 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007755 }
Willy Tarreau102df612014-05-07 23:56:38 +02007756 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7757 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7758 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007759 }
7760 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007761
7762 /* create the task associated with the proxy */
7763 curproxy->task = task_new();
7764 if (curproxy->task) {
7765 curproxy->task->context = curproxy;
7766 curproxy->task->process = manage_proxy;
7767 /* no need to queue, it will be done automatically if some
7768 * listener gets limited.
7769 */
7770 curproxy->task->expire = TICK_ETERNITY;
7771 } else {
7772 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7773 curproxy->id);
7774 cfgerr++;
7775 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007776 }
7777
Willy Tarreaufbb78422011-06-05 15:38:35 +02007778 /* automatically compute fullconn if not set. We must not do it in the
7779 * loop above because cross-references are not yet fully resolved.
7780 */
7781 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7782 /* If <fullconn> is not set, let's set it to 10% of the sum of
7783 * the possible incoming frontend's maxconns.
7784 */
7785 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7786 struct proxy *fe;
7787 int total = 0;
7788
7789 /* sum up the number of maxconns of frontends which
7790 * reference this backend at least once or which are
7791 * the same one ('listen').
7792 */
7793 for (fe = proxy; fe; fe = fe->next) {
7794 struct switching_rule *rule;
7795 struct hdr_exp *exp;
7796 int found = 0;
7797
7798 if (!(fe->cap & PR_CAP_FE))
7799 continue;
7800
7801 if (fe == curproxy) /* we're on a "listen" instance */
7802 found = 1;
7803
7804 if (fe->defbe.be == curproxy) /* "default_backend" */
7805 found = 1;
7806
7807 /* check if a "use_backend" rule matches */
7808 if (!found) {
7809 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007810 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007811 found = 1;
7812 break;
7813 }
7814 }
7815 }
7816
7817 /* check if a "reqsetbe" rule matches */
7818 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7819 if (exp->action == ACT_SETBE &&
7820 (struct proxy *)exp->replace == curproxy) {
7821 found = 1;
7822 break;
7823 }
7824 }
7825
7826 /* now we've checked all possible ways to reference a backend
7827 * from a frontend.
7828 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007829 if (!found)
7830 continue;
7831 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007832 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007833 /* we have the sum of the maxconns in <total>. We only
7834 * keep 10% of that sum to set the default fullconn, with
7835 * a hard minimum of 1 (to avoid a divide by zero).
7836 */
7837 curproxy->fullconn = (total + 9) / 10;
7838 if (!curproxy->fullconn)
7839 curproxy->fullconn = 1;
7840 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007841 }
7842
Willy Tarreau056f5682010-06-06 15:51:11 +02007843 /* initialize stick-tables on backend capable proxies. This must not
7844 * be done earlier because the data size may be discovered while parsing
7845 * other proxies.
7846 */
Godbach9703e662013-12-11 21:11:41 +08007847 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007848 if (curproxy->state == PR_STSTOPPED)
7849 continue;
7850
Godbach9703e662013-12-11 21:11:41 +08007851 if (!stktable_init(&curproxy->table)) {
7852 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7853 cfgerr++;
7854 }
7855 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007856
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007857 /*
7858 * Recount currently required checks.
7859 */
7860
7861 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7862 int optnum;
7863
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007864 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7865 if (curproxy->options & cfg_opts[optnum].val)
7866 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007867
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007868 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7869 if (curproxy->options2 & cfg_opts2[optnum].val)
7870 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007871 }
7872
Willy Tarreau122541c2011-09-07 21:24:49 +02007873 if (peers) {
7874 struct peers *curpeers = peers, **last;
7875 struct peer *p, *pb;
7876
7877 /* Remove all peers sections which don't have a valid listener.
7878 * This can happen when a peers section is never referenced and
7879 * does not contain a local peer.
7880 */
7881 last = &peers;
7882 while (*last) {
7883 curpeers = *last;
7884 if (curpeers->peers_fe) {
7885 last = &curpeers->next;
7886 continue;
7887 }
7888
7889 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7890 curpeers->id, localpeer);
7891
7892 p = curpeers->remote;
7893 while (p) {
7894 pb = p->next;
7895 free(p->id);
7896 free(p);
7897 p = pb;
7898 }
7899
7900 /* Destroy and unlink this curpeers section.
7901 * Note: curpeers is backed up into *last.
7902 */
7903 free(curpeers->id);
7904 curpeers = curpeers->next;
7905 free(*last);
7906 *last = curpeers;
7907 }
7908 }
7909
Simon Horman0d16a402015-01-30 11:22:58 +09007910 if (mailers) {
7911 struct mailers *curmailers = mailers, **last;
7912 struct mailer *m, *mb;
7913
7914 /* Remove all mailers sections which don't have a valid listener.
7915 * This can happen when a mailers section is never referenced.
7916 */
7917 last = &mailers;
7918 while (*last) {
7919 curmailers = *last;
7920 if (curmailers->users) {
7921 last = &curmailers->next;
7922 continue;
7923 }
7924
7925 Warning("Removing incomplete section 'mailers %s'.\n",
7926 curmailers->id);
7927
7928 m = curmailers->mailer_list;
7929 while (m) {
7930 mb = m->next;
7931 free(m->id);
7932 free(m);
7933 m = mb;
7934 }
7935
7936 /* Destroy and unlink this curmailers section.
7937 * Note: curmailers is backed up into *last.
7938 */
7939 free(curmailers->id);
7940 curmailers = curmailers->next;
7941 free(*last);
7942 *last = curmailers;
7943 }
7944 }
7945
Willy Tarreau34eb6712011-10-24 18:15:04 +02007946 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007947 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007948 MEM_F_SHARED);
7949
Willy Tarreaubb925012009-07-23 13:36:36 +02007950 if (cfgerr > 0)
7951 err_code |= ERR_ALERT | ERR_FATAL;
7952 out:
7953 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007954}
7955
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007956/*
7957 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7958 * parsing sessions.
7959 */
7960void cfg_register_keywords(struct cfg_kw_list *kwl)
7961{
7962 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7963}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007964
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007965/*
7966 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7967 */
7968void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7969{
7970 LIST_DEL(&kwl->list);
7971 LIST_INIT(&kwl->list);
7972}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007973
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007974/* this function register new section in the haproxy configuration file.
7975 * <section_name> is the name of this new section and <section_parser>
7976 * is the called parser. If two section declaration have the same name,
7977 * only the first declared is used.
7978 */
7979int cfg_register_section(char *section_name,
7980 int (*section_parser)(const char *, int, char **, int))
7981{
7982 struct cfg_section *cs;
7983
7984 cs = calloc(1, sizeof(*cs));
7985 if (!cs) {
7986 Alert("register section '%s': out of memory.\n", section_name);
7987 return 0;
7988 }
7989
7990 cs->section_name = section_name;
7991 cs->section_parser = section_parser;
7992
7993 LIST_ADDQ(&sections, &cs->list);
7994
7995 return 1;
7996}
7997
Willy Tarreaubaaee002006-06-26 02:48:02 +02007998/*
7999 * Local variables:
8000 * c-indent-level: 8
8001 * c-basic-offset: 8
8002 * End:
8003 */