blob: de940744e1a4fdd64bc7b544cd3432cbdae21b5a [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);
2022 if (!proto || !proto->connect) {
2023 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2024 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 Horman9dc49962015-01-30 11:22:59 +09006610 if (
6611 (curproxy->email_alert.mailers.name || curproxy->email_alert.from || curproxy->email_alert.myhostname || curproxy->email_alert.to) &&
6612 !(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' requrires each of"
6615 "'email-alert from', 'email-alert mailer' and 'email-alert to' to be present).\n",
6616 proxy_type_str(curproxy), curproxy->id);
6617 err_code |= ERR_WARN;
6618 free_email_alert(curproxy);
6619 }
6620
Simon Horman98637e52014-06-20 12:30:16 +09006621 if (curproxy->check_command) {
6622 int clear = 0;
6623 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6624 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6625 "external-check command", proxy_type_str(curproxy), curproxy->id);
6626 err_code |= ERR_WARN;
6627 clear = 1;
6628 }
6629 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6630 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6631 curproxy->id, "external-check command");
6632 cfgerr++;
6633 }
6634 if (clear) {
6635 free(curproxy->check_command);
6636 curproxy->check_command = NULL;
6637 }
6638 }
6639
6640 if (curproxy->check_path) {
6641 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6642 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6643 "external-check path", proxy_type_str(curproxy), curproxy->id);
6644 err_code |= ERR_WARN;
6645 free(curproxy->check_path);
6646 curproxy->check_path = NULL;
6647 }
6648 }
6649
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006650 /* if a default backend was specified, let's find it */
6651 if (curproxy->defbe.name) {
6652 struct proxy *target;
6653
Alex Williams96532db2009-11-01 21:27:13 -05006654 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006655 if (!target) {
6656 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6657 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006658 cfgerr++;
6659 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006660 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6661 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006662 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006663 } else {
6664 free(curproxy->defbe.name);
6665 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006666
6667 /* Emit a warning if this proxy also has some servers */
6668 if (curproxy->srv) {
6669 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6670 curproxy->id);
6671 err_code |= ERR_WARN;
6672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006673 }
6674 }
6675
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006676 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006677 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6678 /* map jump target for ACT_SETBE in req_rep chain */
6679 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006680 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006681 struct proxy *target;
6682
Willy Tarreaua496b602006-12-17 23:15:24 +01006683 if (exp->action != ACT_SETBE)
6684 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006685
Alex Williams96532db2009-11-01 21:27:13 -05006686 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006687 if (!target) {
6688 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6689 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006690 cfgerr++;
6691 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006692 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6693 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006694 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006695 } else {
6696 free((void *)exp->replace);
6697 exp->replace = (const char *)target;
6698 }
6699 }
6700 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006701
6702 /* find the target proxy for 'use_backend' rules */
6703 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006704 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006705 struct logformat_node *node;
6706 char *pxname;
6707
6708 /* Try to parse the string as a log format expression. If the result
6709 * of the parsing is only one entry containing a simple string, then
6710 * it's a standard string corresponding to a static rule, thus the
6711 * parsing is cancelled and be.name is restored to be resolved.
6712 */
6713 pxname = rule->be.name;
6714 LIST_INIT(&rule->be.expr);
6715 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6716 curproxy->conf.args.file, curproxy->conf.args.line);
6717 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6718
6719 if (!LIST_ISEMPTY(&rule->be.expr)) {
6720 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6721 rule->dynamic = 1;
6722 free(pxname);
6723 continue;
6724 }
6725 /* simple string: free the expression and fall back to static rule */
6726 free(node->arg);
6727 free(node);
6728 }
6729
6730 rule->dynamic = 0;
6731 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006732
Alex Williams96532db2009-11-01 21:27:13 -05006733 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006734
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006735 if (!target) {
6736 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6737 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006738 cfgerr++;
6739 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006740 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6741 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006742 cfgerr++;
6743 } else {
6744 free((void *)rule->be.name);
6745 rule->be.backend = target;
6746 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006747 }
6748
Willy Tarreau64ab6072014-09-16 12:17:36 +02006749 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006750 list_for_each_entry(srule, &curproxy->server_rules, list) {
6751 struct server *target = findserver(curproxy, srule->srv.name);
6752
6753 if (!target) {
6754 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6755 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6756 cfgerr++;
6757 continue;
6758 }
6759 free((void *)srule->srv.name);
6760 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006761 }
6762
Emeric Brunb982a3d2010-01-04 15:45:53 +01006763 /* find the target table for 'stick' rules */
6764 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6765 struct proxy *target;
6766
Emeric Brun1d33b292010-01-04 15:47:17 +01006767 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6768 if (mrule->flags & STK_IS_STORE)
6769 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6770
Emeric Brunb982a3d2010-01-04 15:45:53 +01006771 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006772 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006773 else
6774 target = curproxy;
6775
6776 if (!target) {
6777 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6778 curproxy->id, mrule->table.name);
6779 cfgerr++;
6780 }
6781 else if (target->table.size == 0) {
6782 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6783 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6784 cfgerr++;
6785 }
Willy Tarreau12785782012-04-27 21:37:17 +02006786 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6787 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006788 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6789 cfgerr++;
6790 }
6791 else {
6792 free((void *)mrule->table.name);
6793 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006794 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006795 }
6796 }
6797
6798 /* find the target table for 'store response' rules */
6799 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6800 struct proxy *target;
6801
Emeric Brun1d33b292010-01-04 15:47:17 +01006802 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6803
Emeric Brunb982a3d2010-01-04 15:45:53 +01006804 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006805 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006806 else
6807 target = curproxy;
6808
6809 if (!target) {
6810 Alert("Proxy '%s': unable to find store table '%s'.\n",
6811 curproxy->id, mrule->table.name);
6812 cfgerr++;
6813 }
6814 else if (target->table.size == 0) {
6815 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6816 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6817 cfgerr++;
6818 }
Willy Tarreau12785782012-04-27 21:37:17 +02006819 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6820 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006821 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6822 cfgerr++;
6823 }
6824 else {
6825 free((void *)mrule->table.name);
6826 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006827 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006828 }
6829 }
6830
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006831 /* find the target table for 'tcp-request' layer 4 rules */
6832 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6833 struct proxy *target;
6834
Willy Tarreaub4c84932013-07-23 19:15:30 +02006835 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006836 continue;
6837
6838 if (trule->act_prm.trk_ctr.table.n)
6839 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6840 else
6841 target = curproxy;
6842
6843 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006844 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6845 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006846 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006847 cfgerr++;
6848 }
6849 else if (target->table.size == 0) {
6850 Alert("Proxy '%s': table '%s' used but not configured.\n",
6851 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6852 cfgerr++;
6853 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006854 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6855 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6856 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 +01006857 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006858 cfgerr++;
6859 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006860 else {
6861 free(trule->act_prm.trk_ctr.table.n);
6862 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006863 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006864 * to pass a list of counters to track and allocate them right here using
6865 * stktable_alloc_data_type().
6866 */
6867 }
6868 }
6869
Willy Tarreaud1f96522010-08-03 19:34:32 +02006870 /* find the target table for 'tcp-request' layer 6 rules */
6871 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6872 struct proxy *target;
6873
Willy Tarreaub4c84932013-07-23 19:15:30 +02006874 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006875 continue;
6876
6877 if (trule->act_prm.trk_ctr.table.n)
6878 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6879 else
6880 target = curproxy;
6881
6882 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006883 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6884 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006885 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006886 cfgerr++;
6887 }
6888 else if (target->table.size == 0) {
6889 Alert("Proxy '%s': table '%s' used but not configured.\n",
6890 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6891 cfgerr++;
6892 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006893 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6894 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6895 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 +01006896 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006897 cfgerr++;
6898 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006899 else {
6900 free(trule->act_prm.trk_ctr.table.n);
6901 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006902 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006903 * to pass a list of counters to track and allocate them right here using
6904 * stktable_alloc_data_type().
6905 */
6906 }
6907 }
6908
Willy Tarreau09448f72014-06-25 18:12:15 +02006909 /* find the target table for 'http-request' layer 7 rules */
6910 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6911 struct proxy *target;
6912
6913 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6914 continue;
6915
6916 if (hrqrule->act_prm.trk_ctr.table.n)
6917 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6918 else
6919 target = curproxy;
6920
6921 if (!target) {
6922 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6923 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6924 http_req_trk_idx(hrqrule->action));
6925 cfgerr++;
6926 }
6927 else if (target->table.size == 0) {
6928 Alert("Proxy '%s': table '%s' used but not configured.\n",
6929 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6930 cfgerr++;
6931 }
6932 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6933 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6934 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6935 http_req_trk_idx(hrqrule->action));
6936 cfgerr++;
6937 }
6938 else {
6939 free(hrqrule->act_prm.trk_ctr.table.n);
6940 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6941 /* Note: if we decide to enhance the track-sc syntax, we may be able
6942 * to pass a list of counters to track and allocate them right here using
6943 * stktable_alloc_data_type().
6944 */
6945 }
6946 }
6947
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006948 /* move any "block" rules at the beginning of the http-request rules */
6949 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6950 /* insert block_rules into http_req_rules at the beginning */
6951 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6952 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6953 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6954 curproxy->http_req_rules.n = curproxy->block_rules.n;
6955 LIST_INIT(&curproxy->block_rules);
6956 }
6957
Emeric Brun32da3c42010-09-23 18:39:19 +02006958 if (curproxy->table.peers.name) {
6959 struct peers *curpeers = peers;
6960
6961 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6962 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6963 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006964 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006965 break;
6966 }
6967 }
6968
6969 if (!curpeers) {
6970 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6971 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006972 free((void *)curproxy->table.peers.name);
6973 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006974 cfgerr++;
6975 }
6976 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006977 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6978 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006979 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006980 cfgerr++;
6981 }
6982 }
6983
Simon Horman9dc49962015-01-30 11:22:59 +09006984
6985 if (curproxy->email_alert.mailers.name) {
6986 struct mailers *curmailers = mailers;
6987
6988 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
6989 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
6990 free(curproxy->email_alert.mailers.name);
6991 curproxy->email_alert.mailers.m = curmailers;
6992 curmailers->users++;
6993 break;
6994 }
6995 }
6996
6997 if (!curmailers) {
6998 Alert("Proxy '%s': unable to find mailers '%s'.\n",
6999 curproxy->id, curproxy->email_alert.mailers.name);
7000 free_email_alert(curproxy);
7001 cfgerr++;
7002 }
7003 }
7004
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007005 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007006 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007007 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7008 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7009 "proxy", curproxy->id);
7010 cfgerr++;
7011 goto out_uri_auth_compat;
7012 }
7013
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007014 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007015 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007016 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007017 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007018
Willy Tarreau95fa4692010-02-01 13:05:50 +01007019 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7020 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007021
7022 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007023 uri_auth_compat_req[i++] = "realm";
7024 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7025 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007026
Willy Tarreau95fa4692010-02-01 13:05:50 +01007027 uri_auth_compat_req[i++] = "unless";
7028 uri_auth_compat_req[i++] = "{";
7029 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7030 uri_auth_compat_req[i++] = "}";
7031 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007032
Willy Tarreauff011f22011-01-06 17:51:27 +01007033 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7034 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007035 cfgerr++;
7036 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007037 }
7038
Willy Tarreauff011f22011-01-06 17:51:27 +01007039 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007040
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007041 if (curproxy->uri_auth->auth_realm) {
7042 free(curproxy->uri_auth->auth_realm);
7043 curproxy->uri_auth->auth_realm = NULL;
7044 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007045
7046 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007047 }
7048out_uri_auth_compat:
7049
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007050 /* compile the log format */
7051 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007052 if (curproxy->conf.logformat_string != default_http_log_format &&
7053 curproxy->conf.logformat_string != default_tcp_log_format &&
7054 curproxy->conf.logformat_string != clf_http_log_format)
7055 free(curproxy->conf.logformat_string);
7056 curproxy->conf.logformat_string = NULL;
7057 free(curproxy->conf.lfs_file);
7058 curproxy->conf.lfs_file = NULL;
7059 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007060 }
7061
Willy Tarreau62a61232013-04-12 18:13:46 +02007062 if (curproxy->conf.logformat_string) {
7063 curproxy->conf.args.ctx = ARGC_LOG;
7064 curproxy->conf.args.file = curproxy->conf.lfs_file;
7065 curproxy->conf.args.line = curproxy->conf.lfs_line;
7066 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007067 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007068 curproxy->conf.args.file = NULL;
7069 curproxy->conf.args.line = 0;
7070 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007071
Willy Tarreau62a61232013-04-12 18:13:46 +02007072 if (curproxy->conf.uniqueid_format_string) {
7073 curproxy->conf.args.ctx = ARGC_UIF;
7074 curproxy->conf.args.file = curproxy->conf.uif_file;
7075 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007076 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007077 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007078 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007079 curproxy->conf.args.file = NULL;
7080 curproxy->conf.args.line = 0;
7081 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007082
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007083 /* only now we can check if some args remain unresolved.
7084 * This must be done after the users and groups resolution.
7085 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007086 cfgerr += smp_resolve_args(curproxy);
7087 if (!cfgerr)
7088 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007089
Willy Tarreau2738a142006-07-08 17:28:09 +02007090 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007091 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007092 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007093 (!curproxy->timeout.connect ||
7094 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007095 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007096 " | While not properly invalid, you will certainly encounter various problems\n"
7097 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007098 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007099 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007100 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007101 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007102
Willy Tarreau1fa31262007-12-03 00:36:16 +01007103 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7104 * We must still support older configurations, so let's find out whether those
7105 * parameters have been set or must be copied from contimeouts.
7106 */
7107 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007108 if (!curproxy->timeout.tarpit ||
7109 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007110 /* tarpit timeout not set. We search in the following order:
7111 * default.tarpit, curr.connect, default.connect.
7112 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007113 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007114 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007115 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007116 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007117 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007118 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007119 }
7120 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007121 (!curproxy->timeout.queue ||
7122 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007123 /* queue timeout not set. We search in the following order:
7124 * default.queue, curr.connect, default.connect.
7125 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007126 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007127 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007128 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007129 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007130 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007131 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007132 }
7133 }
7134
Willy Tarreau1620ec32011-08-06 17:05:02 +02007135 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007136 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7137 curproxy->check_req = (char *)malloc(curproxy->check_len);
7138 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007139 }
7140
Willy Tarreau215663d2014-06-13 18:30:23 +02007141 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7142 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7143 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7144 proxy_type_str(curproxy), curproxy->id);
7145 err_code |= ERR_WARN;
7146 }
7147
Willy Tarreau193b8c62012-11-22 00:17:38 +01007148 /* ensure that cookie capture length is not too large */
7149 if (curproxy->capture_len >= global.tune.cookie_len) {
7150 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7151 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7152 err_code |= ERR_WARN;
7153 curproxy->capture_len = global.tune.cookie_len - 1;
7154 }
7155
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007156 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007157 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007158 curproxy->req_cap_pool = create_pool("ptrcap",
7159 curproxy->nb_req_cap * sizeof(char *),
7160 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007161 }
7162
7163 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007164 curproxy->rsp_cap_pool = create_pool("ptrcap",
7165 curproxy->nb_rsp_cap * sizeof(char *),
7166 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007167 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007168
Willy Tarreaubaaee002006-06-26 02:48:02 +02007169 /* first, we will invert the servers list order */
7170 newsrv = NULL;
7171 while (curproxy->srv) {
7172 struct server *next;
7173
7174 next = curproxy->srv->next;
7175 curproxy->srv->next = newsrv;
7176 newsrv = curproxy->srv;
7177 if (!next)
7178 break;
7179 curproxy->srv = next;
7180 }
7181
Willy Tarreau17edc812014-01-03 12:14:34 +01007182 /* Check that no server name conflicts. This causes trouble in the stats.
7183 * We only emit a warning for the first conflict affecting each server,
7184 * in order to avoid combinatory explosion if all servers have the same
7185 * name. We do that only for servers which do not have an explicit ID,
7186 * because these IDs were made also for distinguishing them and we don't
7187 * want to annoy people who correctly manage them.
7188 */
7189 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7190 struct server *other_srv;
7191
7192 if (newsrv->puid)
7193 continue;
7194
7195 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7196 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7197 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7198 newsrv->conf.file, newsrv->conf.line,
7199 proxy_type_str(curproxy), curproxy->id,
7200 newsrv->id, other_srv->conf.line);
7201 break;
7202 }
7203 }
7204 }
7205
Willy Tarreaudd701652010-05-25 23:03:02 +02007206 /* assign automatic UIDs to servers which don't have one yet */
7207 next_id = 1;
7208 newsrv = curproxy->srv;
7209 while (newsrv != NULL) {
7210 if (!newsrv->puid) {
7211 /* server ID not set, use automatic numbering with first
7212 * spare entry starting with next_svid.
7213 */
7214 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7215 newsrv->conf.id.key = newsrv->puid = next_id;
7216 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7217 }
7218 next_id++;
7219 newsrv = newsrv->next;
7220 }
7221
Willy Tarreau20697042007-11-15 23:26:18 +01007222 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007223 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007224
Willy Tarreau62c3be22012-01-20 13:12:32 +01007225 /*
7226 * If this server supports a maxconn parameter, it needs a dedicated
7227 * tasks to fill the emptied slots when a connection leaves.
7228 * Also, resolve deferred tracking dependency if needed.
7229 */
7230 newsrv = curproxy->srv;
7231 while (newsrv != NULL) {
7232 if (newsrv->minconn > newsrv->maxconn) {
7233 /* Only 'minconn' was specified, or it was higher than or equal
7234 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7235 * this will avoid further useless expensive computations.
7236 */
7237 newsrv->maxconn = newsrv->minconn;
7238 } else if (newsrv->maxconn && !newsrv->minconn) {
7239 /* minconn was not specified, so we set it to maxconn */
7240 newsrv->minconn = newsrv->maxconn;
7241 }
7242
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007243#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007244 if (newsrv->use_ssl || newsrv->check.use_ssl)
7245 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007246#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007247
Willy Tarreau2f075e92013-12-03 11:11:34 +01007248 /* set the check type on the server */
7249 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7250
Willy Tarreau62c3be22012-01-20 13:12:32 +01007251 if (newsrv->trackit) {
7252 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007253 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007254 char *pname, *sname;
7255
7256 pname = newsrv->trackit;
7257 sname = strrchr(pname, '/');
7258
7259 if (sname)
7260 *sname++ = '\0';
7261 else {
7262 sname = pname;
7263 pname = NULL;
7264 }
7265
7266 if (pname) {
7267 px = findproxy(pname, PR_CAP_BE);
7268 if (!px) {
7269 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7270 proxy_type_str(curproxy), curproxy->id,
7271 newsrv->id, pname);
7272 cfgerr++;
7273 goto next_srv;
7274 }
7275 } else
7276 px = curproxy;
7277
7278 srv = findserver(px, sname);
7279 if (!srv) {
7280 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7281 proxy_type_str(curproxy), curproxy->id,
7282 newsrv->id, sname);
7283 cfgerr++;
7284 goto next_srv;
7285 }
7286
Willy Tarreau32091232014-05-16 13:52:00 +02007287 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7288 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7289 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007290 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007291 "tracking as it does not have any check nor agent enabled.\n",
7292 proxy_type_str(curproxy), curproxy->id,
7293 newsrv->id, px->id, srv->id);
7294 cfgerr++;
7295 goto next_srv;
7296 }
7297
7298 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7299
7300 if (loop) {
7301 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7302 "belongs to a tracking chain looping back to %s/%s.\n",
7303 proxy_type_str(curproxy), curproxy->id,
7304 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007305 cfgerr++;
7306 goto next_srv;
7307 }
7308
7309 if (curproxy != px &&
7310 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7311 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7312 "tracking: disable-on-404 option inconsistency.\n",
7313 proxy_type_str(curproxy), curproxy->id,
7314 newsrv->id, px->id, srv->id);
7315 cfgerr++;
7316 goto next_srv;
7317 }
7318
7319 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007320 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007321 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007322 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007323 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007324 }
7325
7326 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007327 newsrv->tracknext = srv->trackers;
7328 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007329
7330 free(newsrv->trackit);
7331 newsrv->trackit = NULL;
7332 }
7333 next_srv:
7334 newsrv = newsrv->next;
7335 }
7336
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007337 /* We have to initialize the server lookup mechanism depending
7338 * on what LB algorithm was choosen.
7339 */
7340
7341 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7342 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7343 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007344 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7345 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7346 init_server_map(curproxy);
7347 } else {
7348 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7349 fwrr_init_server_groups(curproxy);
7350 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007351 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007352
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007353 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007354 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7355 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7356 fwlc_init_server_tree(curproxy);
7357 } else {
7358 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7359 fas_init_server_tree(curproxy);
7360 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007361 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007362
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007363 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007364 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7365 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7366 chash_init_server_tree(curproxy);
7367 } else {
7368 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7369 init_server_map(curproxy);
7370 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007371 break;
7372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007373
7374 if (curproxy->options & PR_O_LOGASAP)
7375 curproxy->to_log &= ~LW_BYTES;
7376
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007377 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007378 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007379 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7380 proxy_type_str(curproxy), curproxy->id);
7381 err_code |= ERR_WARN;
7382 }
7383
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007384 if (curproxy->mode != PR_MODE_HTTP) {
7385 int optnum;
7386
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007387 if (curproxy->uri_auth) {
7388 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7389 proxy_type_str(curproxy), curproxy->id);
7390 err_code |= ERR_WARN;
7391 curproxy->uri_auth = NULL;
7392 }
7393
Willy Tarreau87cf5142011-08-19 22:57:24 +02007394 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007395 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7396 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7397 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007398 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007399 }
7400
7401 if (curproxy->options & PR_O_ORGTO) {
7402 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7403 "originalto", proxy_type_str(curproxy), curproxy->id);
7404 err_code |= ERR_WARN;
7405 curproxy->options &= ~PR_O_ORGTO;
7406 }
7407
7408 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7409 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7410 (curproxy->cap & cfg_opts[optnum].cap) &&
7411 (curproxy->options & cfg_opts[optnum].val)) {
7412 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7413 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7414 err_code |= ERR_WARN;
7415 curproxy->options &= ~cfg_opts[optnum].val;
7416 }
7417 }
7418
7419 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7420 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7421 (curproxy->cap & cfg_opts2[optnum].cap) &&
7422 (curproxy->options2 & cfg_opts2[optnum].val)) {
7423 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7424 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7425 err_code |= ERR_WARN;
7426 curproxy->options2 &= ~cfg_opts2[optnum].val;
7427 }
7428 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007429
Pieter Baauwd551fb52013-05-08 22:49:23 +02007430#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007431 if (curproxy->conn_src.bind_hdr_occ) {
7432 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007433 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007434 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007435 err_code |= ERR_WARN;
7436 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007437#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007438 }
7439
Willy Tarreaubaaee002006-06-26 02:48:02 +02007440 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007441 * ensure that we're not cross-dressing a TCP server into HTTP.
7442 */
7443 newsrv = curproxy->srv;
7444 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007445 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007446 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7447 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007448 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007449 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007450
Willy Tarreau0cec3312011-10-31 13:49:26 +01007451 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7452 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7453 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7454 err_code |= ERR_WARN;
7455 }
7456
Willy Tarreauc93cd162014-05-13 15:54:22 +02007457 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007458 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7459 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7460 err_code |= ERR_WARN;
7461 }
7462
Pieter Baauwd551fb52013-05-08 22:49:23 +02007463#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007464 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7465 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007466 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 +01007467 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007468 err_code |= ERR_WARN;
7469 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007470#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007471 newsrv = newsrv->next;
7472 }
7473
Willy Tarreaue42bd962014-09-16 16:21:19 +02007474 /* check if we have a frontend with "tcp-request content" looking at L7
7475 * with no inspect-delay
7476 */
7477 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7478 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7479 if (trule->action == TCP_ACT_CAPTURE &&
7480 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7481 break;
7482 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7483 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7484 break;
7485 }
7486
7487 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7488 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7489 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7490 " This means that these rules will randomly find their contents. This can be fixed by"
7491 " setting the tcp-request inspect-delay.\n",
7492 proxy_type_str(curproxy), curproxy->id);
7493 err_code |= ERR_WARN;
7494 }
7495 }
7496
Willy Tarreauc1a21672009-08-16 22:37:44 +02007497 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007498 if (!curproxy->accept)
7499 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007500
Willy Tarreauc1a21672009-08-16 22:37:44 +02007501 if (curproxy->tcp_req.inspect_delay ||
7502 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007503 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007504
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007505 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007506 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007507 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007508 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007509
7510 /* both TCP and HTTP must check switching rules */
7511 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7512 }
7513
7514 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007515 if (curproxy->tcp_req.inspect_delay ||
7516 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7517 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7518
Emeric Brun97679e72010-09-23 17:56:44 +02007519 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7520 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7521
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007522 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007523 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007524 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007525 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007526
7527 /* If the backend does requires RDP cookie persistence, we have to
7528 * enable the corresponding analyser.
7529 */
7530 if (curproxy->options2 & PR_O2_RDPC_PRST)
7531 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7532 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007533 }
7534
7535 /***********************************************************/
7536 /* At this point, target names have already been resolved. */
7537 /***********************************************************/
7538
7539 /* Check multi-process mode compatibility */
7540
7541 if (global.nbproc > 1 && global.stats_fe) {
7542 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7543 unsigned long mask;
7544
7545 mask = nbits(global.nbproc);
7546 if (global.stats_fe->bind_proc)
7547 mask &= global.stats_fe->bind_proc;
7548
7549 if (bind_conf->bind_proc)
7550 mask &= bind_conf->bind_proc;
7551
7552 /* stop here if more than one process is used */
7553 if (popcount(mask) > 1)
7554 break;
7555 }
7556 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7557 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");
7558 }
7559 }
7560
7561 /* Make each frontend inherit bind-process from its listeners when not specified. */
7562 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7563 if (curproxy->bind_proc)
7564 continue;
7565
7566 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7567 unsigned long mask;
7568
7569 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7570 curproxy->bind_proc |= mask;
7571 }
7572
7573 if (!curproxy->bind_proc)
7574 curproxy->bind_proc = ~0UL;
7575 }
7576
7577 if (global.stats_fe) {
7578 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7579 unsigned long mask;
7580
7581 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7582 global.stats_fe->bind_proc |= mask;
7583 }
7584 if (!global.stats_fe->bind_proc)
7585 global.stats_fe->bind_proc = ~0UL;
7586 }
7587
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007588 /* propagate bindings from frontends to backends. Don't do it if there
7589 * are any fatal errors as we must not call it with unresolved proxies.
7590 */
7591 if (!cfgerr) {
7592 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7593 if (curproxy->cap & PR_CAP_FE)
7594 propagate_processes(curproxy, NULL);
7595 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007596 }
7597
7598 /* Bind each unbound backend to all processes when not specified. */
7599 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7600 if (curproxy->bind_proc)
7601 continue;
7602 curproxy->bind_proc = ~0UL;
7603 }
7604
7605 /*******************************************************/
7606 /* At this step, all proxies have a non-null bind_proc */
7607 /*******************************************************/
7608
7609 /* perform the final checks before creating tasks */
7610
7611 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7612 struct listener *listener;
7613 unsigned int next_id;
7614 int nbproc;
7615
7616 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007617
Emeric Brunc52962f2012-11-15 18:28:02 +01007618#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007619 /* Configure SSL for each bind line.
7620 * Note: if configuration fails at some point, the ->ctx member
7621 * remains NULL so that listeners can later detach.
7622 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007623 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007624 int alloc_ctx;
7625
Emeric Brunc52962f2012-11-15 18:28:02 +01007626 if (!bind_conf->is_ssl) {
7627 if (bind_conf->default_ctx) {
7628 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7629 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7630 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007631 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007632 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007633 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007634 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007635 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007636 cfgerr++;
7637 continue;
7638 }
7639
Emeric Brun8dc60392014-05-09 13:52:00 +02007640 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007641 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007642 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7643 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");
7644 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007645 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007646 cfgerr++;
7647 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007648 }
7649
Emeric Brunfc0421f2012-09-07 17:30:07 +02007650 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007651 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007652 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007653#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007654
Willy Tarreaue6b98942007-10-29 01:09:36 +01007655 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007656 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007657 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007658 if (!listener->luid) {
7659 /* listener ID not set, use automatic numbering with first
7660 * spare entry starting with next_luid.
7661 */
7662 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7663 listener->conf.id.key = listener->luid = next_id;
7664 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007665 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007666 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007667
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007668 /* enable separate counters */
7669 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7670 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007671 if (!listener->name)
7672 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007673 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007674
Willy Tarreaue6b98942007-10-29 01:09:36 +01007675 if (curproxy->options & PR_O_TCP_NOLING)
7676 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007677 if (!listener->maxconn)
7678 listener->maxconn = curproxy->maxconn;
7679 if (!listener->backlog)
7680 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007681 if (!listener->maxaccept)
7682 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7683
7684 /* we want to have an optimal behaviour on single process mode to
7685 * maximize the work at once, but in multi-process we want to keep
7686 * some fairness between processes, so we target half of the max
7687 * number of events to be balanced over all the processes the proxy
7688 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7689 * used to disable the limit.
7690 */
7691 if (listener->maxaccept > 0) {
7692 if (nbproc > 1)
7693 listener->maxaccept = (listener->maxaccept + 1) / 2;
7694 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7695 }
7696
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007697 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007698 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007699 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007700 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007701
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007702 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7703 listener->options |= LI_O_TCP_RULES;
7704
Willy Tarreaude3041d2010-05-31 10:56:17 +02007705 if (curproxy->mon_mask.s_addr)
7706 listener->options |= LI_O_CHK_MONNET;
7707
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007708 /* smart accept mode is automatic in HTTP mode */
7709 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007710 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007711 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7712 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007713 }
7714
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007715 /* Release unused SSL configs */
7716 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7717 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007718 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007719#ifdef USE_OPENSSL
7720 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007721 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007722 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007723 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007724 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007725#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007726 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007727
Willy Tarreau102df612014-05-07 23:56:38 +02007728 if (nbproc > 1) {
7729 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007730 int count, maxproc = 0;
7731
7732 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7733 count = popcount(bind_conf->bind_proc);
7734 if (count > maxproc)
7735 maxproc = count;
7736 }
7737 /* backends have 0, frontends have 1 or more */
7738 if (maxproc != 1)
7739 Warning("Proxy '%s': in multi-process mode, stats will be"
7740 " limited to process assigned to the current request.\n",
7741 curproxy->id);
7742
Willy Tarreau102df612014-05-07 23:56:38 +02007743 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7744 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7745 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007746 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007747 }
Willy Tarreau102df612014-05-07 23:56:38 +02007748 if (curproxy->appsession_name) {
7749 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7750 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007751 }
Willy Tarreau102df612014-05-07 23:56:38 +02007752 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7753 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7754 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007755 }
7756 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007757
7758 /* create the task associated with the proxy */
7759 curproxy->task = task_new();
7760 if (curproxy->task) {
7761 curproxy->task->context = curproxy;
7762 curproxy->task->process = manage_proxy;
7763 /* no need to queue, it will be done automatically if some
7764 * listener gets limited.
7765 */
7766 curproxy->task->expire = TICK_ETERNITY;
7767 } else {
7768 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7769 curproxy->id);
7770 cfgerr++;
7771 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007772 }
7773
Willy Tarreaufbb78422011-06-05 15:38:35 +02007774 /* automatically compute fullconn if not set. We must not do it in the
7775 * loop above because cross-references are not yet fully resolved.
7776 */
7777 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7778 /* If <fullconn> is not set, let's set it to 10% of the sum of
7779 * the possible incoming frontend's maxconns.
7780 */
7781 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7782 struct proxy *fe;
7783 int total = 0;
7784
7785 /* sum up the number of maxconns of frontends which
7786 * reference this backend at least once or which are
7787 * the same one ('listen').
7788 */
7789 for (fe = proxy; fe; fe = fe->next) {
7790 struct switching_rule *rule;
7791 struct hdr_exp *exp;
7792 int found = 0;
7793
7794 if (!(fe->cap & PR_CAP_FE))
7795 continue;
7796
7797 if (fe == curproxy) /* we're on a "listen" instance */
7798 found = 1;
7799
7800 if (fe->defbe.be == curproxy) /* "default_backend" */
7801 found = 1;
7802
7803 /* check if a "use_backend" rule matches */
7804 if (!found) {
7805 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007806 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007807 found = 1;
7808 break;
7809 }
7810 }
7811 }
7812
7813 /* check if a "reqsetbe" rule matches */
7814 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7815 if (exp->action == ACT_SETBE &&
7816 (struct proxy *)exp->replace == curproxy) {
7817 found = 1;
7818 break;
7819 }
7820 }
7821
7822 /* now we've checked all possible ways to reference a backend
7823 * from a frontend.
7824 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007825 if (!found)
7826 continue;
7827 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007828 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007829 /* we have the sum of the maxconns in <total>. We only
7830 * keep 10% of that sum to set the default fullconn, with
7831 * a hard minimum of 1 (to avoid a divide by zero).
7832 */
7833 curproxy->fullconn = (total + 9) / 10;
7834 if (!curproxy->fullconn)
7835 curproxy->fullconn = 1;
7836 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007837 }
7838
Willy Tarreau056f5682010-06-06 15:51:11 +02007839 /* initialize stick-tables on backend capable proxies. This must not
7840 * be done earlier because the data size may be discovered while parsing
7841 * other proxies.
7842 */
Godbach9703e662013-12-11 21:11:41 +08007843 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007844 if (curproxy->state == PR_STSTOPPED)
7845 continue;
7846
Godbach9703e662013-12-11 21:11:41 +08007847 if (!stktable_init(&curproxy->table)) {
7848 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7849 cfgerr++;
7850 }
7851 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007852
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007853 /*
7854 * Recount currently required checks.
7855 */
7856
7857 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7858 int optnum;
7859
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007860 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7861 if (curproxy->options & cfg_opts[optnum].val)
7862 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007863
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007864 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7865 if (curproxy->options2 & cfg_opts2[optnum].val)
7866 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007867 }
7868
Willy Tarreau122541c2011-09-07 21:24:49 +02007869 if (peers) {
7870 struct peers *curpeers = peers, **last;
7871 struct peer *p, *pb;
7872
7873 /* Remove all peers sections which don't have a valid listener.
7874 * This can happen when a peers section is never referenced and
7875 * does not contain a local peer.
7876 */
7877 last = &peers;
7878 while (*last) {
7879 curpeers = *last;
7880 if (curpeers->peers_fe) {
7881 last = &curpeers->next;
7882 continue;
7883 }
7884
7885 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7886 curpeers->id, localpeer);
7887
7888 p = curpeers->remote;
7889 while (p) {
7890 pb = p->next;
7891 free(p->id);
7892 free(p);
7893 p = pb;
7894 }
7895
7896 /* Destroy and unlink this curpeers section.
7897 * Note: curpeers is backed up into *last.
7898 */
7899 free(curpeers->id);
7900 curpeers = curpeers->next;
7901 free(*last);
7902 *last = curpeers;
7903 }
7904 }
7905
Simon Horman0d16a402015-01-30 11:22:58 +09007906 if (mailers) {
7907 struct mailers *curmailers = mailers, **last;
7908 struct mailer *m, *mb;
7909
7910 /* Remove all mailers sections which don't have a valid listener.
7911 * This can happen when a mailers section is never referenced.
7912 */
7913 last = &mailers;
7914 while (*last) {
7915 curmailers = *last;
7916 if (curmailers->users) {
7917 last = &curmailers->next;
7918 continue;
7919 }
7920
7921 Warning("Removing incomplete section 'mailers %s'.\n",
7922 curmailers->id);
7923
7924 m = curmailers->mailer_list;
7925 while (m) {
7926 mb = m->next;
7927 free(m->id);
7928 free(m);
7929 m = mb;
7930 }
7931
7932 /* Destroy and unlink this curmailers section.
7933 * Note: curmailers is backed up into *last.
7934 */
7935 free(curmailers->id);
7936 curmailers = curmailers->next;
7937 free(*last);
7938 *last = curmailers;
7939 }
7940 }
7941
Willy Tarreau34eb6712011-10-24 18:15:04 +02007942 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007943 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007944 MEM_F_SHARED);
7945
Willy Tarreaubb925012009-07-23 13:36:36 +02007946 if (cfgerr > 0)
7947 err_code |= ERR_ALERT | ERR_FATAL;
7948 out:
7949 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007950}
7951
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007952/*
7953 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7954 * parsing sessions.
7955 */
7956void cfg_register_keywords(struct cfg_kw_list *kwl)
7957{
7958 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7959}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007960
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007961/*
7962 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7963 */
7964void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7965{
7966 LIST_DEL(&kwl->list);
7967 LIST_INIT(&kwl->list);
7968}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007969
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007970/* this function register new section in the haproxy configuration file.
7971 * <section_name> is the name of this new section and <section_parser>
7972 * is the called parser. If two section declaration have the same name,
7973 * only the first declared is used.
7974 */
7975int cfg_register_section(char *section_name,
7976 int (*section_parser)(const char *, int, char **, int))
7977{
7978 struct cfg_section *cs;
7979
7980 cs = calloc(1, sizeof(*cs));
7981 if (!cs) {
7982 Alert("register section '%s': out of memory.\n", section_name);
7983 return 0;
7984 }
7985
7986 cs->section_name = section_name;
7987 cs->section_parser = section_parser;
7988
7989 LIST_ADDQ(&sections, &cs->list);
7990
7991 return 1;
7992}
7993
Willy Tarreaubaaee002006-06-26 02:48:02 +02007994/*
7995 * Local variables:
7996 * c-indent-level: 8
7997 * c-basic-offset: 8
7998 * End:
7999 */