blob: b0e636ce83ad8a55005f0566db44281e097bdea2 [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>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
William Lallemand9ed62032016-11-21 17:49:11 +010062#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020063#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020064#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020065#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020066#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010067#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020068#include <proto/lb_fwlc.h>
69#include <proto/lb_fwrr.h>
70#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020071#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010074#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020075#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020083#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020084#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010085#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
Emeric Brunfc0421f2012-09-07 17:30:07 +020087#ifdef USE_OPENSSL
88#include <types/ssl_sock.h>
89#include <proto/ssl_sock.h>
90#include <proto/shctx.h>
91#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020092
Willy Tarreauf3c69202006-07-09 16:42:34 +020093/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
94 * ssl-hello-chk option to ensure that the remote server speaks SSL.
95 *
96 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
97 */
98const char sslv3_client_hello_pkt[] = {
99 "\x16" /* ContentType : 0x16 = Hanshake */
100 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
101 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
102 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
103 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
104 "\x03\x00" /* Hello Version : 0x0300 = v3 */
105 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
106 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
107 "\x00" /* Session ID length : empty (no session ID) */
108 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
109 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
110 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
111 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
112 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
113 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
114 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
115 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
116 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
117 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
118 "\x00\x38" "\x00\x39" "\x00\x3A"
119 "\x01" /* Compression Length : 0x01 = 1 byte for types */
120 "\x00" /* Compression Type : 0x00 = NULL compression */
121};
122
Willy Tarreau3842f002009-06-14 11:39:52 +0200123/* various keyword modifiers */
124enum kw_mod {
125 KWM_STD = 0, /* normal */
126 KWM_NO, /* "no" prefixed before the keyword */
127 KWM_DEF, /* "default" prefixed before the keyword */
128};
129
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100130/* permit to store configuration section */
131struct cfg_section {
132 struct list list;
133 char *section_name;
134 int (*section_parser)(const char *, int, char **, int);
135};
136
137/* Used to chain configuration sections definitions. This list
138 * stores struct cfg_section
139 */
140struct list sections = LIST_HEAD_INIT(sections);
141
Willy Tarreau13943ab2006-12-31 00:24:10 +0100142/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100144 const char *name;
145 unsigned int val;
146 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100147 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100149};
150
151/* proxy->options */
152static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100153{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
155 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
156 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
157 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
158 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
159 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200161 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200162 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100163 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
165 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
166 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100168#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100170#else
171 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100172#endif
173
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100175};
176
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100177/* proxy->options2 */
178static const struct cfg_opt cfg_opts2[] =
179{
180#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
183 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100184#else
185 { "splice-request", 0, 0, 0, 0 },
186 { "splice-response", 0, 0, 0, 0 },
187 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100188#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100189 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
190 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
191 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
192 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
193 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
194 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
196 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
197 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400198 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100199 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200200 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200201 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100202 { NULL, 0, 0, 0 }
203};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204
Willy Tarreau6daf3432008-01-22 16:44:08 +0100205static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
207int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100208int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100209char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200211/* List head of all known configuration keywords */
212static struct cfg_kw_list cfg_keywords = {
213 .list = LIST_HEAD_INIT(cfg_keywords.list)
214};
215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216/*
217 * converts <str> to a list of listeners which are dynamically allocated.
218 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
219 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
220 * - <port> is a numerical port from 1 to 65535 ;
221 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
222 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
224 * not NULL, it must be a valid pointer to either NULL or a freeable area that
225 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200227int 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 +0200228{
229 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 int port, end;
232
233 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200234
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100236 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100237 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
239 str = next;
240 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100241 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 *next++ = 0;
243 }
244
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100245 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200246 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200247 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100248 if (!ss2)
249 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100251 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200253 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100257 if (!port || !end) {
258 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
259 goto fail;
260 }
261
Emeric Bruned760922010-10-22 17:59:25 +0200262 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
266
267 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200268 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200269 goto fail;
270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100272 else if (ss2->ss_family == AF_UNSPEC) {
273 socklen_t addr_len;
274
275 /* We want to attach to an already bound fd whose number
276 * is in the addr part of ss2 when cast to sockaddr_in.
277 * Note that by definition there is a single listener.
278 * We still have to determine the address family to
279 * register the correct protocol.
280 */
281 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
282 addr_len = sizeof(*ss2);
283 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
284 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
285 goto fail;
286 }
287
288 port = end = get_host_port(ss2);
289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100291 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200292 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100293
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200295 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100296 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200297 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
298 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
299 l->frontend = curproxy;
300 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301
Willy Tarreau40aa0702013-03-10 23:51:38 +0100302 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200303 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200304 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100305 l->state = LI_INIT;
306
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100307 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100309 tcpv4_add_listener(l);
310 }
Emeric Bruned760922010-10-22 17:59:25 +0200311 else if (ss.ss_family == AF_INET6) {
312 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
313 tcpv6_add_listener(l);
314 }
315 else {
Emeric Bruned760922010-10-22 17:59:25 +0200316 uxst_add_listener(l);
317 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200319 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100320 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 } /* end for(port) */
322 } /* end while(next) */
323 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200324 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325 fail:
326 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200327 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328}
329
William Lallemand6e62fb62015-04-28 16:55:23 +0200330/*
331 * Report a fatal Alert when there is too much arguments
332 * The index is the current keyword in args
333 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
334 * Fill err_code with an ERR_ALERT and an ERR_FATAL
335 */
336int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
337{
338 char *kw = NULL;
339 int i;
340
341 if (!*args[index + maxarg + 1])
342 return 0;
343
344 memprintf(&kw, "%s", args[0]);
345 for (i = 1; i <= index; i++) {
346 memprintf(&kw, "%s %s", kw, args[i]);
347 }
348
349 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
350 free(kw);
351 *err_code |= ERR_ALERT | ERR_FATAL;
352 return 1;
353}
354
355/*
356 * same as alertif_too_many_args_idx with a 0 index
357 */
358int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
359{
360 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
361}
362
Willy Tarreau620408f2016-10-21 16:37:51 +0200363/* Report a warning if a rule is placed after a 'tcp-request session' rule.
364 * Return 1 if the warning has been emitted, otherwise 0.
365 */
366int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
367{
368 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
369 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
370 file, line, arg);
371 return 1;
372 }
373 return 0;
374}
375
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200376/* Report a warning if a rule is placed after a 'tcp-request content' rule.
377 * Return 1 if the warning has been emitted, otherwise 0.
378 */
379int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
380{
381 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
382 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
383 file, line, arg);
384 return 1;
385 }
386 return 0;
387}
388
Willy Tarreau61d18892009-03-31 10:49:21 +0200389/* Report a warning if a rule is placed after a 'block' rule.
390 * Return 1 if the warning has been emitted, otherwise 0.
391 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200394 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200395 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
396 file, line, arg);
397 return 1;
398 }
399 return 0;
400}
401
Willy Tarreau5002f572014-04-23 01:32:02 +0200402/* Report a warning if a rule is placed after an 'http_request' rule.
403 * Return 1 if the warning has been emitted, otherwise 0.
404 */
405int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
406{
407 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
408 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
409 file, line, arg);
410 return 1;
411 }
412 return 0;
413}
414
Willy Tarreau61d18892009-03-31 10:49:21 +0200415/* Report a warning if a rule is placed after a reqrewrite rule.
416 * Return 1 if the warning has been emitted, otherwise 0.
417 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100418int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200419{
420 if (proxy->req_exp) {
421 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
422 file, line, arg);
423 return 1;
424 }
425 return 0;
426}
427
428/* Report a warning if a rule is placed after a reqadd rule.
429 * Return 1 if the warning has been emitted, otherwise 0.
430 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100431int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200432{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100433 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200434 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
435 file, line, arg);
436 return 1;
437 }
438 return 0;
439}
440
441/* Report a warning if a rule is placed after a redirect rule.
442 * Return 1 if the warning has been emitted, otherwise 0.
443 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100444int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200445{
446 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
447 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
448 file, line, arg);
449 return 1;
450 }
451 return 0;
452}
453
454/* Report a warning if a rule is placed after a 'use_backend' rule.
455 * Return 1 if the warning has been emitted, otherwise 0.
456 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100457int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200458{
459 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
460 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
461 file, line, arg);
462 return 1;
463 }
464 return 0;
465}
466
Willy Tarreauee445d92014-04-23 01:39:04 +0200467/* Report a warning if a rule is placed after a 'use-server' rule.
468 * Return 1 if the warning has been emitted, otherwise 0.
469 */
470int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
471{
472 if (!LIST_ISEMPTY(&proxy->server_rules)) {
473 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
474 file, line, arg);
475 return 1;
476 }
477 return 0;
478}
479
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200480/* report a warning if a "tcp request connection" rule is dangerously placed */
481int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
482{
Willy Tarreau620408f2016-10-21 16:37:51 +0200483 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
484 warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
485 warnif_rule_after_block(proxy, file, line, arg) ||
486 warnif_rule_after_http_req(proxy, file, line, arg) ||
487 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
488 warnif_rule_after_reqadd(proxy, file, line, arg) ||
489 warnif_rule_after_redirect(proxy, file, line, arg) ||
490 warnif_rule_after_use_backend(proxy, file, line, arg) ||
491 warnif_rule_after_use_server(proxy, file, line, arg);
492}
493
494int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
495{
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200496 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
497 warnif_rule_after_block(proxy, file, line, arg) ||
498 warnif_rule_after_http_req(proxy, file, line, arg) ||
499 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
500 warnif_rule_after_reqadd(proxy, file, line, arg) ||
501 warnif_rule_after_redirect(proxy, file, line, arg) ||
502 warnif_rule_after_use_backend(proxy, file, line, arg) ||
503 warnif_rule_after_use_server(proxy, file, line, arg);
504}
505
506/* report a warning if a "tcp request content" rule is dangerously placed */
507int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
508{
509 return warnif_rule_after_block(proxy, file, line, arg) ||
510 warnif_rule_after_http_req(proxy, file, line, arg) ||
511 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
512 warnif_rule_after_reqadd(proxy, file, line, arg) ||
513 warnif_rule_after_redirect(proxy, file, line, arg) ||
514 warnif_rule_after_use_backend(proxy, file, line, arg) ||
515 warnif_rule_after_use_server(proxy, file, line, arg);
516}
517
Willy Tarreau61d18892009-03-31 10:49:21 +0200518/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100519int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200520{
Willy Tarreau5002f572014-04-23 01:32:02 +0200521 return warnif_rule_after_http_req(proxy, file, line, arg) ||
522 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
523 warnif_rule_after_reqadd(proxy, file, line, arg) ||
524 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200525 warnif_rule_after_use_backend(proxy, file, line, arg) ||
526 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200527}
528
529/* report a warning if an http-request rule is dangerously placed */
530int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
531{
Willy Tarreau61d18892009-03-31 10:49:21 +0200532 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
533 warnif_rule_after_reqadd(proxy, file, line, arg) ||
534 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200535 warnif_rule_after_use_backend(proxy, file, line, arg) ||
536 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200537}
538
539/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100540int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200541{
542 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
543 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200544 warnif_rule_after_use_backend(proxy, file, line, arg) ||
545 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200546}
547
548/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100549int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200550{
551 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200552 warnif_rule_after_use_backend(proxy, file, line, arg) ||
553 warnif_rule_after_use_server(proxy, file, line, arg);
554}
555
556/* report a warning if a redirect rule is dangerously placed */
557int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
558{
559 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
560 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200561}
562
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100563/* Report it if a request ACL condition uses some keywords that are incompatible
564 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
565 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
566 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100569{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100570 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200571 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100574 return 0;
575
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100576 acl = acl_cond_conflicts(cond, where);
577 if (acl) {
578 if (acl->name && *acl->name)
579 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
580 file, line, acl->name, sample_ckp_names(where));
581 else
582 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 +0200583 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100584 return ERR_WARN;
585 }
586 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100587 return 0;
588
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100589 if (acl->name && *acl->name)
590 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200591 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100592 else
593 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200594 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100595 return ERR_WARN;
596}
597
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200599 * parse a line in a <global> section. Returns the error code, 0 if OK, or
600 * any combination of :
601 * - ERR_ABORT: must abort ASAP
602 * - ERR_FATAL: we can continue parsing but not start the service
603 * - ERR_WARN: a warning has been emitted
604 * - ERR_ALERT: an alert has been emitted
605 * Only the two first ones can stop processing, the two others are just
606 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200608int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609{
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200611 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612
613 if (!strcmp(args[0], "global")) { /* new section */
614 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200615 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200618 else if (!strcmp(args[0], "ca-base")) {
619#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200620 if(alertif_too_many_args(1, file, linenum, args, &err_code))
621 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200622 if (global.ca_base != NULL) {
623 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT;
625 goto out;
626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631 }
632 global.ca_base = strdup(args[1]);
633#else
634 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
637#endif
638 }
639 else if (!strcmp(args[0], "crt-base")) {
640#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(1, file, linenum, args, &err_code))
642 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200643 if (global.crt_base != NULL) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.crt_base = strdup(args[1]);
654#else
655 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
656 err_code |= ERR_ALERT | ERR_FATAL;
657 goto out;
658#endif
659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 global.mode |= MODE_DAEMON;
664 }
665 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 global.mode |= MODE_DEBUG;
669 }
670 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(0, file, linenum, args, &err_code))
672 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100673 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200675 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200676 if (alertif_too_many_args(0, file, linenum, args, &err_code))
677 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100678 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200681 if (alertif_too_many_args(0, file, linenum, args, &err_code))
682 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100683 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100685 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(0, file, linenum, args, &err_code))
687 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100688 global.tune.options &= ~GTUNE_USE_SPLICE;
689 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200690 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200691 if (alertif_too_many_args(0, file, linenum, args, &err_code))
692 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200693 global.tune.options &= ~GTUNE_USE_GAI;
694 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000695 else if (!strcmp(args[0], "noreuseport")) {
696 if (alertif_too_many_args(0, file, linenum, args, &err_code))
697 goto out;
698 global.tune.options &= ~GTUNE_USE_REUSEPORT;
699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200701 if (alertif_too_many_args(0, file, linenum, args, &err_code))
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 global.mode |= MODE_QUIET;
704 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200705 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
707 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200708 if (global.tune.maxpollevents != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200710 err_code |= ERR_ALERT;
711 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200717 }
718 global.tune.maxpollevents = atol(args[1]);
719 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100720 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200721 if (alertif_too_many_args(1, file, linenum, args, &err_code))
722 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100723 if (global.tune.maxaccept != 0) {
724 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT;
726 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100727 }
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100732 }
733 global.tune.maxaccept = atol(args[1]);
734 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200735 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200736 if (alertif_too_many_args(1, file, linenum, args, &err_code))
737 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.chksize = atol(args[1]);
744 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100745 else if (!strcmp(args[0], "tune.recv_enough")) {
746 if (alertif_too_many_args(1, file, linenum, args, &err_code))
747 goto out;
748 if (*(args[1]) == 0) {
749 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
752 }
753 global.tune.recv_enough = atol(args[1]);
754 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200755#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200756 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200757 if (alertif_too_many_args(0, file, linenum, args, &err_code))
758 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200759 global.tune.sslprivatecache = 1;
760 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100761 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
763 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200764 if (*(args[1]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 global.tune.sslcachesize = atol(args[1]);
770 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100771 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
772 unsigned int ssllifetime;
773 const char *res;
774
William Lallemand1a748ae2015-05-19 16:37:23 +0200775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
776 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782
783 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
784 if (res) {
785 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
786 file, linenum, *res, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790
791 global.tune.ssllifetime = ssllifetime;
792 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100793 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200794 if (alertif_too_many_args(1, file, linenum, args, &err_code))
795 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100796 if (*(args[1]) == 0) {
797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801 global.tune.ssl_max_record = atol(args[1]);
802 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200803#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200804 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.ssl_default_dh_param = atol(args[1]);
813 if (global.tune.ssl_default_dh_param < 1024) {
814 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200819#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200820 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.tune.ssl_ctx_cache = atoi(args[1]);
829 if (global.tune.ssl_ctx_cache < 0) {
830 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
831 file, linenum, args[0]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200836#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100837 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200838 if (alertif_too_many_args(1, file, linenum, args, &err_code))
839 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100840 if (*(args[1]) == 0) {
841 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
842 err_code |= ERR_ALERT | ERR_FATAL;
843 goto out;
844 }
845 global.tune.buf_limit = atol(args[1]);
846 if (global.tune.buf_limit) {
847 if (global.tune.buf_limit < 3)
848 global.tune.buf_limit = 3;
849 if (global.tune.buf_limit <= global.tune.reserved_bufs)
850 global.tune.buf_limit = global.tune.reserved_bufs + 1;
851 }
852 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100853 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200854 if (alertif_too_many_args(1, file, linenum, args, &err_code))
855 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100856 if (*(args[1]) == 0) {
857 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
858 err_code |= ERR_ALERT | ERR_FATAL;
859 goto out;
860 }
861 global.tune.reserved_bufs = atol(args[1]);
862 if (global.tune.reserved_bufs < 2)
863 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100864 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
865 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100866 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200867 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200868 if (alertif_too_many_args(1, file, linenum, args, &err_code))
869 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200876 if (global.tune.bufsize <= 0) {
877 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100881 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100882 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200883 }
884 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200885 if (alertif_too_many_args(1, file, linenum, args, &err_code))
886 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200893 if (global.tune.maxrewrite < 0) {
894 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200898 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100899 else if (!strcmp(args[0], "tune.idletimer")) {
900 unsigned int idle;
901 const char *res;
902
William Lallemand1a748ae2015-05-19 16:37:23 +0200903 if (alertif_too_many_args(1, file, linenum, args, &err_code))
904 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100905 if (*(args[1]) == 0) {
906 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910
911 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
912 if (res) {
913 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
914 file, linenum, *res, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918
919 if (idle > 65535) {
920 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
924 global.tune.idle_timer = idle;
925 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100926 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200927 if (alertif_too_many_args(1, file, linenum, args, &err_code))
928 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100929 if (global.tune.client_rcvbuf != 0) {
930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT;
932 goto out;
933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.tune.client_rcvbuf = atol(args[1]);
940 }
941 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
943 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100944 if (global.tune.server_rcvbuf != 0) {
945 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT;
947 goto out;
948 }
949 if (*(args[1]) == 0) {
950 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 global.tune.server_rcvbuf = atol(args[1]);
955 }
956 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200957 if (alertif_too_many_args(1, file, linenum, args, &err_code))
958 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100959 if (global.tune.client_sndbuf != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
961 err_code |= ERR_ALERT;
962 goto out;
963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.tune.client_sndbuf = atol(args[1]);
970 }
971 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200972 if (alertif_too_many_args(1, file, linenum, args, &err_code))
973 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100974 if (global.tune.server_sndbuf != 0) {
975 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
976 err_code |= ERR_ALERT;
977 goto out;
978 }
979 if (*(args[1]) == 0) {
980 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
983 }
984 global.tune.server_sndbuf = atol(args[1]);
985 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200986 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200987 if (alertif_too_many_args(1, file, linenum, args, &err_code))
988 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 global.tune.pipesize = atol(args[1]);
995 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100996 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200997 if (alertif_too_many_args(1, file, linenum, args, &err_code))
998 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 global.tune.cookie_len = atol(args[1]) + 1;
1005 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001006 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001007 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1008 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +02001009 if (*(args[1]) == 0) {
1010 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.tune.max_http_hdr = atol(args[1]);
1015 }
William Lallemanda509e4c2012-11-07 16:54:34 +01001016 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
1017#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001018 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1019 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001020 if (*args[1]) {
1021 global.tune.zlibmemlevel = atoi(args[1]);
1022 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
1023 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1024 file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 } else {
1029 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1030 file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034#else
1035 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038#endif
1039 }
1040 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1041#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001042 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1043 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001044 if (*args[1]) {
1045 global.tune.zlibwindowsize = atoi(args[1]);
1046 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1047 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1048 file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 } else {
1053 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1054 file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058#else
1059 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062#endif
1063 }
William Lallemandf3747832012-11-09 12:33:10 +01001064 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001065 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1066 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001067 if (*args[1]) {
1068 global.tune.comp_maxlevel = atoi(args[1]);
1069 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1070 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1071 file, linenum, args[0]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 } else {
1076 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1077 file, linenum, args[0]);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001082 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1083 if (*args[1]) {
1084 global.tune.pattern_cache = atoi(args[1]);
1085 if (global.tune.pattern_cache < 0) {
1086 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1087 file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 } else {
1092 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1093 file, linenum, args[0]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001099 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001102 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001103 err_code |= ERR_ALERT;
1104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 }
1106 if (*(args[1]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001111 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1112 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
1113 err_code |= ERR_WARN;
1114 goto out;
1115 }
1116
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 }
1118 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001119 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001122 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 }
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001131 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1132 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
1133 err_code |= ERR_WARN;
1134 goto out;
1135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
Simon Horman98637e52014-06-20 12:30:16 +09001137 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001138 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1139 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001140 global.external_check = 1;
1141 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001142 /* user/group name handling */
1143 else if (!strcmp(args[0], "user")) {
1144 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001147 if (global.uid != 0) {
1148 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT;
1150 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001151 }
1152 errno = 0;
1153 ha_user = getpwnam(args[1]);
1154 if (ha_user != NULL) {
1155 global.uid = (int)ha_user->pw_uid;
1156 }
1157 else {
1158 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 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001160 }
1161 }
1162 else if (!strcmp(args[0], "group")) {
1163 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001164 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1165 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001166 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001167 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001168 err_code |= ERR_ALERT;
1169 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001170 }
1171 errno = 0;
1172 ha_group = getgrnam(args[1]);
1173 if (ha_group != NULL) {
1174 global.gid = (int)ha_group->gr_gid;
1175 }
1176 else {
1177 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 +02001178 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001179 }
1180 }
1181 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001183 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185 if (*(args[1]) == 0) {
1186 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 }
1190 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001191 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1192 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1193 file, linenum, args[0], LONGBITS, global.nbproc);
1194 err_code |= ERR_ALERT | ERR_FATAL;
1195 goto out;
1196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 }
1198 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001199 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 if (global.maxconn != 0) {
1202 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001203 err_code |= ERR_ALERT;
1204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
1206 if (*(args[1]) == 0) {
1207 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 }
1211 global.maxconn = atol(args[1]);
1212#ifdef SYSTEM_MAXCONN
1213 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1214 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);
1215 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001216 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218#endif /* SYSTEM_MAXCONN */
1219 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001220 else if (!strcmp(args[0], "maxsslconn")) {
1221#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001222 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1223 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 global.maxsslconn = atol(args[1]);
1230#else
Emeric Brun0914df82012-10-02 18:45:42 +02001231 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001234#endif
1235 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001236 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1237#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001238 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1239 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001240 if (*(args[1]) == 0) {
1241 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245 free(global.listen_default_ciphers);
1246 global.listen_default_ciphers = strdup(args[1]);
1247#else
1248 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251#endif
1252 }
1253 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1254#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001255 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1256 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001257 if (*(args[1]) == 0) {
1258 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262 free(global.connect_default_ciphers);
1263 global.connect_default_ciphers = strdup(args[1]);
1264#else
1265 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268#endif
1269 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001270#ifdef USE_OPENSSL
1271#ifndef OPENSSL_NO_DH
1272 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1279 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282 }
1283 }
1284#endif
1285#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001286 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001287 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1288 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001289 if (*(args[1]) == 0) {
1290 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
1293 }
1294 if (strcmp(args[1],"none") == 0)
1295 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1296 else if (strcmp(args[1],"required") == 0)
1297 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1298 else {
1299 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001304 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001305 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1306 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001307 if (global.cps_lim != 0) {
1308 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1309 err_code |= ERR_ALERT;
1310 goto out;
1311 }
1312 if (*(args[1]) == 0) {
1313 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1314 err_code |= ERR_ALERT | ERR_FATAL;
1315 goto out;
1316 }
1317 global.cps_lim = atol(args[1]);
1318 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001319 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001320 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1321 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001322 if (global.sps_lim != 0) {
1323 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1324 err_code |= ERR_ALERT;
1325 goto out;
1326 }
1327 if (*(args[1]) == 0) {
1328 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332 global.sps_lim = atol(args[1]);
1333 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001334 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001335 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1336 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001337 if (global.ssl_lim != 0) {
1338 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1339 err_code |= ERR_ALERT;
1340 goto out;
1341 }
1342 if (*(args[1]) == 0) {
1343 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
1346 }
1347 global.ssl_lim = atol(args[1]);
1348 }
William Lallemandd85f9172012-11-09 17:05:39 +01001349 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001350 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1351 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001352 if (*(args[1]) == 0) {
1353 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357 global.comp_rate_lim = atoi(args[1]) * 1024;
1358 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001359 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001360 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1361 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001362 if (global.maxpipes != 0) {
1363 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001364 err_code |= ERR_ALERT;
1365 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001366 }
1367 if (*(args[1]) == 0) {
1368 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001369 err_code |= ERR_ALERT | ERR_FATAL;
1370 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001371 }
1372 global.maxpipes = atol(args[1]);
1373 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001374 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001375 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1376 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001377 if (*(args[1]) == 0) {
1378 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto out;
1381 }
William Lallemande3a7d992012-11-20 11:25:20 +01001382 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001383 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001384 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001385 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1386 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001387 if (*(args[1]) == 0) {
1388 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1389 err_code |= ERR_ALERT | ERR_FATAL;
1390 goto out;
1391 }
1392 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001393 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001394 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
1397 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001398 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001399
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001401 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 if (global.rlimit_nofile != 0) {
1404 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001405 err_code |= ERR_ALERT;
1406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 }
1408 if (*(args[1]) == 0) {
1409 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 }
1413 global.rlimit_nofile = atol(args[1]);
1414 }
1415 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001416 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 if (global.chroot != NULL) {
1419 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001420 err_code |= ERR_ALERT;
1421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 }
1423 if (*(args[1]) == 0) {
1424 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001425 err_code |= ERR_ALERT | ERR_FATAL;
1426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 }
1428 global.chroot = strdup(args[1]);
1429 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001430 else if (!strcmp(args[0], "description")) {
1431 int i, len=0;
1432 char *d;
1433
1434 if (!*args[1]) {
1435 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1436 file, linenum, args[0]);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 goto out;
1439 }
1440
Willy Tarreau348acfe2014-04-14 15:00:39 +02001441 for (i = 1; *args[i]; i++)
1442 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001443
1444 if (global.desc)
1445 free(global.desc);
1446
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001447 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001448
Willy Tarreau348acfe2014-04-14 15:00:39 +02001449 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1450 for (i = 2; *args[i]; i++)
1451 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001452 }
1453 else if (!strcmp(args[0], "node")) {
1454 int i;
1455 char c;
1456
William Lallemand1a748ae2015-05-19 16:37:23 +02001457 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1458 goto out;
1459
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001460 for (i=0; args[1][i]; i++) {
1461 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001462 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1463 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001464 break;
1465 }
1466
1467 if (!i || args[1][i]) {
1468 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1469 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1470 file, linenum, args[0]);
1471 err_code |= ERR_ALERT | ERR_FATAL;
1472 goto out;
1473 }
1474
1475 if (global.node)
1476 free(global.node);
1477
1478 global.node = strdup(args[1]);
1479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001481 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 if (global.pidfile != NULL) {
1484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001485 err_code |= ERR_ALERT;
1486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 }
1488 if (*(args[1]) == 0) {
1489 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 }
1493 global.pidfile = strdup(args[1]);
1494 }
Emeric Bruned760922010-10-22 17:59:25 +02001495 else if (!strcmp(args[0], "unix-bind")) {
1496 int cur_arg = 1;
1497 while (*(args[cur_arg])) {
1498 if (!strcmp(args[cur_arg], "prefix")) {
1499 if (global.unix_bind.prefix != NULL) {
1500 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1501 err_code |= ERR_ALERT;
1502 cur_arg += 2;
1503 continue;
1504 }
1505
1506 if (*(args[cur_arg+1]) == 0) {
1507 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto out;
1510 }
1511 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1512 cur_arg += 2;
1513 continue;
1514 }
1515
1516 if (!strcmp(args[cur_arg], "mode")) {
1517
1518 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1519 cur_arg += 2;
1520 continue;
1521 }
1522
1523 if (!strcmp(args[cur_arg], "uid")) {
1524
1525 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1526 cur_arg += 2;
1527 continue;
1528 }
1529
1530 if (!strcmp(args[cur_arg], "gid")) {
1531
1532 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1533 cur_arg += 2;
1534 continue;
1535 }
1536
1537 if (!strcmp(args[cur_arg], "user")) {
1538 struct passwd *user;
1539
1540 user = getpwnam(args[cur_arg + 1]);
1541 if (!user) {
1542 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1543 file, linenum, args[0], args[cur_arg + 1 ]);
1544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
1547
1548 global.unix_bind.ux.uid = user->pw_uid;
1549 cur_arg += 2;
1550 continue;
1551 }
1552
1553 if (!strcmp(args[cur_arg], "group")) {
1554 struct group *group;
1555
1556 group = getgrnam(args[cur_arg + 1]);
1557 if (!group) {
1558 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1559 file, linenum, args[0], args[cur_arg + 1 ]);
1560 err_code |= ERR_ALERT | ERR_FATAL;
1561 goto out;
1562 }
1563
1564 global.unix_bind.ux.gid = group->gr_gid;
1565 cur_arg += 2;
1566 continue;
1567 }
1568
Willy Tarreaub48f9582011-09-05 01:17:06 +02001569 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001570 file, linenum, args[0]);
1571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
1573 }
1574 }
William Lallemand0f99e342011-10-12 17:50:54 +02001575 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1576 /* delete previous herited or defined syslog servers */
1577 struct logsrv *back;
1578 struct logsrv *tmp;
1579
1580 if (*(args[1]) != 0) {
1581 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1582 err_code |= ERR_ALERT | ERR_FATAL;
1583 goto out;
1584 }
1585
1586 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1587 LIST_DEL(&tmp->list);
1588 free(tmp);
1589 }
1590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001592 struct sockaddr_storage *sk;
1593 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001594 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001595 int arg = 0;
1596 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001597
William Lallemand1a748ae2015-05-19 16:37:23 +02001598 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1599 goto out;
1600
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 if (*(args[1]) == 0 || *(args[2]) == 0) {
1602 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
1604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
William Lallemand0f99e342011-10-12 17:50:54 +02001606
Vincent Bernat02779b62016-04-03 13:48:43 +02001607 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001608
Willy Tarreau18324f52014-06-27 18:10:07 +02001609 /* just after the address, a length may be specified */
1610 if (strcmp(args[arg+2], "len") == 0) {
1611 len = atoi(args[arg+3]);
1612 if (len < 80 || len > 65535) {
1613 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1614 file, linenum, args[arg+3]);
1615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
1617 }
1618 logsrv->maxlen = len;
1619
1620 /* skip these two args */
1621 arg += 2;
1622 }
1623 else
1624 logsrv->maxlen = MAX_SYSLOG_LEN;
1625
1626 if (logsrv->maxlen > global.max_syslog_len) {
1627 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001628 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1629 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1630 logline = my_realloc2(logline, global.max_syslog_len + 1);
1631 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001632 }
1633
Dragan Dosen1322d092015-09-22 16:05:32 +02001634 /* after the length, a format may be specified */
1635 if (strcmp(args[arg+2], "format") == 0) {
1636 logsrv->format = get_log_format(args[arg+3]);
1637 if (logsrv->format < 0) {
1638 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1639 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001640 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001641 goto out;
1642 }
1643
1644 /* skip these two args */
1645 arg += 2;
1646 }
1647
David Carlier97880bb2016-04-08 10:35:26 +01001648 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1649 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001650 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001651 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001652
Willy Tarreau18324f52014-06-27 18:10:07 +02001653 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001654 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001655 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001657 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 }
1659
William Lallemand0f99e342011-10-12 17:50:54 +02001660 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001661 if (*(args[arg+3])) {
1662 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001663 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001664 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001666 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 }
1668 }
1669
William Lallemand0f99e342011-10-12 17:50:54 +02001670 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001671 if (*(args[arg+4])) {
1672 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001673 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001674 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001676 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001677 }
1678 }
1679
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001680 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001681 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001682 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001683 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001684 free(logsrv);
1685 goto out;
1686 }
1687 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001688
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001689 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001690 if (port1 != port2) {
1691 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1692 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001693 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001694 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001695 goto out;
1696 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001697
William Lallemand0f99e342011-10-12 17:50:54 +02001698 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001699 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001700 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702
William Lallemand0f99e342011-10-12 17:50:54 +02001703 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001704 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001705 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1706 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001707
1708 if (global.log_send_hostname != NULL) {
1709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1710 err_code |= ERR_ALERT;
1711 goto out;
1712 }
1713
1714 if (*(args[1]))
1715 name = args[1];
1716 else
1717 name = hostname;
1718
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001719 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001720 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001721 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001722 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1723 if (global.server_state_base != NULL) {
1724 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1725 err_code |= ERR_ALERT;
1726 goto out;
1727 }
1728
1729 if (!*(args[1])) {
1730 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1731 err_code |= ERR_FATAL;
1732 goto out;
1733 }
1734
1735 global.server_state_base = strdup(args[1]);
1736 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001737 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1738 if (global.server_state_file != NULL) {
1739 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1740 err_code |= ERR_ALERT;
1741 goto out;
1742 }
1743
1744 if (!*(args[1])) {
1745 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1746 err_code |= ERR_FATAL;
1747 goto out;
1748 }
1749
1750 global.server_state_file = strdup(args[1]);
1751 }
Kevinm48936af2010-12-22 16:08:21 +00001752 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001753 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1754 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001755 if (*(args[1]) == 0) {
1756 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001760 chunk_destroy(&global.log_tag);
1761 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001762 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001763 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001764 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1765 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001766 if (global.spread_checks != 0) {
1767 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001768 err_code |= ERR_ALERT;
1769 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001770 }
1771 if (*(args[1]) == 0) {
1772 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001775 }
1776 global.spread_checks = atol(args[1]);
1777 if (global.spread_checks < 0 || global.spread_checks > 50) {
1778 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001779 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001782 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1783 const char *err;
1784 unsigned int val;
1785
William Lallemand1a748ae2015-05-19 16:37:23 +02001786 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1787 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001788 if (*(args[1]) == 0) {
1789 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
1792 }
1793
1794 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1795 if (err) {
1796 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 }
1799 global.max_spread_checks = val;
1800 if (global.max_spread_checks < 0) {
1801 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 }
1804 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001805 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1806#ifdef USE_CPU_AFFINITY
1807 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001808 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001809 unsigned long cpus = 0;
1810
1811 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001812 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001813 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001814 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001815 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001816 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001817 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001818 proc = atol(args[1]);
1819 if (proc >= 1 && proc <= LONGBITS)
1820 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001821 }
1822
1823 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001824 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",
1825 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
1828 }
1829
1830 cur_arg = 2;
1831 while (*args[cur_arg]) {
1832 unsigned int low, high;
1833
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001834 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001835 char *dash = strchr(args[cur_arg], '-');
1836
1837 low = high = str2uic(args[cur_arg]);
1838 if (dash)
1839 high = str2uic(dash + 1);
1840
1841 if (high < low) {
1842 unsigned int swap = low;
1843 low = high;
1844 high = swap;
1845 }
1846
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001847 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001848 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001849 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001850 err_code |= ERR_ALERT | ERR_FATAL;
1851 goto out;
1852 }
1853
1854 while (low <= high)
1855 cpus |= 1UL << low++;
1856 }
1857 else {
1858 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1859 file, linenum, args[0], args[cur_arg]);
1860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
1862 }
1863 cur_arg++;
1864 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001865 for (i = 0; i < LONGBITS; i++)
1866 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001867 global.cpu_map[i] = cpus;
1868#else
1869 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872#endif
1873 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001874 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1875 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1876 goto out;
1877
1878 if (*(args[2]) == 0) {
1879 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
1882 }
1883
1884 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1885 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1886 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
1889 }
1890 }
1891 else if (!strcmp(args[0], "unsetenv")) {
1892 int arg;
1893
1894 if (*(args[1]) == 0) {
1895 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
1898 }
1899
1900 for (arg = 1; *args[arg]; arg++) {
1901 if (unsetenv(args[arg]) != 0) {
1902 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1903 err_code |= ERR_ALERT | ERR_FATAL;
1904 goto out;
1905 }
1906 }
1907 }
1908 else if (!strcmp(args[0], "resetenv")) {
1909 extern char **environ;
1910 char **env = environ;
1911
1912 /* args contain variable names to keep, one per argument */
1913 while (*env) {
1914 int arg;
1915
1916 /* look for current variable in among all those we want to keep */
1917 for (arg = 1; *args[arg]; arg++) {
1918 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1919 (*env)[strlen(args[arg])] == '=')
1920 break;
1921 }
1922
1923 /* delete this variable */
1924 if (!*args[arg]) {
1925 char *delim = strchr(*env, '=');
1926
1927 if (!delim || delim - *env >= trash.size) {
1928 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
1931 }
1932
1933 memcpy(trash.str, *env, delim - *env);
1934 trash.str[delim - *env] = 0;
1935
1936 if (unsetenv(trash.str) != 0) {
1937 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
1940 }
1941 }
1942 else
1943 env++;
1944 }
1945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001947 struct cfg_kw_list *kwl;
1948 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001949 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001950
1951 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1952 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1953 if (kwl->kw[index].section != CFG_GLOBAL)
1954 continue;
1955 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001956 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001957 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001958 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001959 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001960 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001961 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001962 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001963 err_code |= ERR_WARN;
1964 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001965 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001966 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001967 }
1968 }
1969 }
1970
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001972 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001974
Willy Tarreau058e9072009-07-20 09:30:05 +02001975 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001976 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001977 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978}
1979
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001980void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001982 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 defproxy.mode = PR_MODE_TCP;
1984 defproxy.state = PR_STNEW;
1985 defproxy.maxconn = cfg_maxpconn;
1986 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001987 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001988 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001989
Simon Horman66183002013-02-23 10:16:43 +09001990 defproxy.defsrv.check.inter = DEF_CHKINTR;
1991 defproxy.defsrv.check.fastinter = 0;
1992 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001993 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1994 defproxy.defsrv.agent.fastinter = 0;
1995 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001996 defproxy.defsrv.check.rise = DEF_RISETIME;
1997 defproxy.defsrv.check.fall = DEF_FALLTIME;
1998 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1999 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02002000 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09002001 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002002 defproxy.defsrv.maxqueue = 0;
2003 defproxy.defsrv.minconn = 0;
2004 defproxy.defsrv.maxconn = 0;
2005 defproxy.defsrv.slowstart = 0;
2006 defproxy.defsrv.onerror = DEF_HANA_ONERR;
2007 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
2008 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09002009
2010 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002011 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012}
2013
Willy Tarreauade5ec42010-01-28 19:33:49 +01002014
Willy Tarreau63af98d2014-05-18 08:11:41 +02002015/* This function createss a new req* or rsp* rule to the proxy. It compiles the
2016 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
2017 * ERR_FATAL in case of error.
2018 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01002019static int create_cond_regex_rule(const char *file, int line,
2020 struct proxy *px, int dir, int action, int flags,
2021 const char *cmd, const char *reg, const char *repl,
2022 const char **cond_start)
2023{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002024 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002025 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002026 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002027 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002028 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002029 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002030 int cs;
2031 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002032
2033 if (px == &defproxy) {
2034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002035 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002036 goto err;
2037 }
2038
2039 if (*reg == 0) {
2040 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002041 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002042 goto err;
2043 }
2044
Christopher Faulet898566e2016-10-26 11:06:28 +02002045 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002046 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002047
Willy Tarreau5321c422010-01-28 20:35:13 +01002048 if (cond_start &&
2049 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002050 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2051 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2052 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002053 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002054 goto err;
2055 }
2056 }
2057 else if (cond_start && **cond_start) {
2058 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2059 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002060 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002061 goto err;
2062 }
2063
Willy Tarreau63af98d2014-05-18 08:11:41 +02002064 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002065 (dir == SMP_OPT_DIR_REQ) ?
2066 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2067 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2068 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002069
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002070 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002071 if (!preg) {
2072 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002073 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002074 goto err;
2075 }
2076
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002077 cs = !(flags & REG_ICASE);
2078 cap = !(flags & REG_NOSUB);
2079 error = NULL;
2080 if (!regex_comp(reg, preg, cs, cap, &error)) {
2081 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2082 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002083 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002084 goto err;
2085 }
2086
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002087 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002088 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002089 if (repl && err) {
2090 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2091 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002092 ret_code |= ERR_ALERT | ERR_FATAL;
2093 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002094 }
2095
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002096 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002097 ret_code |= ERR_WARN;
2098
2099 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002100
Willy Tarreau63af98d2014-05-18 08:11:41 +02002101 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002102 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002103 err:
2104 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002105 free(errmsg);
2106 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002107}
2108
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109/*
William Lallemand51097192015-04-14 16:35:22 +02002110 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002111 * Returns the error code, 0 if OK, or any combination of :
2112 * - ERR_ABORT: must abort ASAP
2113 * - ERR_FATAL: we can continue parsing but not start the service
2114 * - ERR_WARN: a warning has been emitted
2115 * - ERR_ALERT: an alert has been emitted
2116 * Only the two first ones can stop processing, the two others are just
2117 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002119int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2120{
2121 static struct peers *curpeers = NULL;
2122 struct peer *newpeer = NULL;
2123 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002124 struct bind_conf *bind_conf;
2125 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002126 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002127 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002128
2129 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002130 if (!*args[1]) {
2131 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002132 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002133 goto out;
2134 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002135
William Lallemand6e62fb62015-04-28 16:55:23 +02002136 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2137 goto out;
2138
Emeric Brun32da3c42010-09-23 18:39:19 +02002139 err = invalid_char(args[1]);
2140 if (err) {
2141 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2142 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002143 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002144 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002145 }
2146
2147 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2148 /*
2149 * If there are two proxies with the same name only following
2150 * combinations are allowed:
2151 */
2152 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002153 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02002154 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002156 }
2157 }
2158
Vincent Bernat02779b62016-04-03 13:48:43 +02002159 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002160 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2161 err_code |= ERR_ALERT | ERR_ABORT;
2162 goto out;
2163 }
2164
2165 curpeers->next = peers;
2166 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002167 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002168 curpeers->conf.line = linenum;
2169 curpeers->last_change = now.tv_sec;
2170 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002171 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002172 }
2173 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002174 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002175 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002176 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002177
2178 if (!*args[2]) {
2179 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2180 file, linenum, args[0]);
2181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
2183 }
2184
2185 err = invalid_char(args[1]);
2186 if (err) {
2187 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2188 file, linenum, *err, args[1]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
Vincent Bernat02779b62016-04-03 13:48:43 +02002193 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2195 err_code |= ERR_ALERT | ERR_ABORT;
2196 goto out;
2197 }
2198
2199 /* the peers are linked backwards first */
2200 curpeers->count++;
2201 newpeer->next = curpeers->remote;
2202 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002203 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002204 newpeer->conf.line = linenum;
2205
2206 newpeer->last_change = now.tv_sec;
2207 newpeer->id = strdup(args[1]);
2208
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002209 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002210 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002211 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002214 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002215
2216 proto = protocol_by_family(sk->ss_family);
2217 if (!proto || !proto->connect) {
2218 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2219 file, linenum, args[0], args[1]);
2220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
2222 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002223
2224 if (port1 != port2) {
2225 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2226 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
2229 }
2230
Willy Tarreau2aa38802013-02-20 19:20:59 +01002231 if (!port1) {
2232 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2233 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002237
Emeric Brun32da3c42010-09-23 18:39:19 +02002238 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002239 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002240 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002241 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002242
Emeric Brun32da3c42010-09-23 18:39:19 +02002243 if (strcmp(newpeer->id, localpeer) == 0) {
2244 /* Current is local peer, it define a frontend */
2245 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002246 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002247
2248 if (!curpeers->peers_fe) {
2249 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2251 err_code |= ERR_ALERT | ERR_ABORT;
2252 goto out;
2253 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002254
Willy Tarreau237250c2011-07-29 01:49:03 +02002255 init_new_proxy(curpeers->peers_fe);
2256 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002257 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002258 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2259 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002260 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002261
2262 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2263
Willy Tarreau902636f2013-03-10 19:44:48 +01002264 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2265 if (errmsg && *errmsg) {
2266 indent_msg(&errmsg, 2);
2267 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002268 }
2269 else
2270 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2271 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002272 err_code |= ERR_FATAL;
2273 goto out;
2274 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002275
2276 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002277 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002278 l->maxconn = curpeers->peers_fe->maxconn;
2279 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002280 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002281 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002282 l->analysers |= curpeers->peers_fe->fe_req_ana;
2283 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002284 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2285 global.maxsock += l->maxconn;
2286 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002287 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002288 else {
2289 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2290 file, linenum, args[0], args[1],
2291 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2292 err_code |= ERR_FATAL;
2293 goto out;
2294 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002295 }
2296 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002297 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2298 curpeers->state = PR_STSTOPPED;
2299 }
2300 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2301 curpeers->state = PR_STNEW;
2302 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002303 else if (*args[0] != 0) {
2304 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308
2309out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002310 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002311 return err_code;
2312}
2313
Baptiste Assmann325137d2015-04-13 23:40:55 +02002314/*
2315 * Parse a <resolvers> section.
2316 * Returns the error code, 0 if OK, or any combination of :
2317 * - ERR_ABORT: must abort ASAP
2318 * - ERR_FATAL: we can continue parsing but not start the service
2319 * - ERR_WARN: a warning has been emitted
2320 * - ERR_ALERT: an alert has been emitted
2321 * Only the two first ones can stop processing, the two others are just
2322 * indicators.
2323 */
2324int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2325{
2326 static struct dns_resolvers *curr_resolvers = NULL;
2327 struct dns_nameserver *newnameserver = NULL;
2328 const char *err;
2329 int err_code = 0;
2330 char *errmsg = NULL;
2331
2332 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2333 if (!*args[1]) {
2334 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2335 err_code |= ERR_ALERT | ERR_ABORT;
2336 goto out;
2337 }
2338
2339 err = invalid_char(args[1]);
2340 if (err) {
2341 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2342 file, linenum, *err, args[0], args[1]);
2343 err_code |= ERR_ALERT | ERR_ABORT;
2344 goto out;
2345 }
2346
2347 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2348 /* Error if two resolvers owns the same name */
2349 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2350 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2351 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2352 err_code |= ERR_ALERT | ERR_ABORT;
2353 }
2354 }
2355
Vincent Bernat02779b62016-04-03 13:48:43 +02002356 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2358 err_code |= ERR_ALERT | ERR_ABORT;
2359 goto out;
2360 }
2361
2362 /* default values */
2363 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2364 curr_resolvers->conf.file = strdup(file);
2365 curr_resolvers->conf.line = linenum;
2366 curr_resolvers->id = strdup(args[1]);
2367 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002368 /* default hold period for nx, other, refuse and timeout is 30s */
2369 curr_resolvers->hold.nx = 30000;
2370 curr_resolvers->hold.other = 30000;
2371 curr_resolvers->hold.refused = 30000;
2372 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002373 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002374 curr_resolvers->hold.valid = 10000;
2375 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002376 curr_resolvers->resolve_retries = 3;
2377 LIST_INIT(&curr_resolvers->nameserver_list);
2378 LIST_INIT(&curr_resolvers->curr_resolution);
2379 }
2380 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2381 struct sockaddr_storage *sk;
2382 int port1, port2;
2383 struct protocol *proto;
2384
2385 if (!*args[2]) {
2386 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2387 file, linenum, args[0]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
2392 err = invalid_char(args[1]);
2393 if (err) {
2394 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2395 file, linenum, *err, args[1]);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
2398 }
2399
Baptiste Assmanna315c552015-11-02 22:55:49 +01002400 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2401 /* Error if two resolvers owns the same name */
2402 if (strcmp(newnameserver->id, args[1]) == 0) {
2403 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2404 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2405 err_code |= ERR_ALERT | ERR_FATAL;
2406 }
2407 }
2408
Vincent Bernat02779b62016-04-03 13:48:43 +02002409 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002410 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2411 err_code |= ERR_ALERT | ERR_ABORT;
2412 goto out;
2413 }
2414
2415 /* the nameservers are linked backward first */
2416 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2417 curr_resolvers->count_nameservers++;
2418 newnameserver->resolvers = curr_resolvers;
2419 newnameserver->conf.file = strdup(file);
2420 newnameserver->conf.line = linenum;
2421 newnameserver->id = strdup(args[1]);
2422
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002423 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002424 if (!sk) {
2425 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 proto = protocol_by_family(sk->ss_family);
2431 if (!proto || !proto->connect) {
2432 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2433 file, linenum, args[0], args[1]);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437
2438 if (port1 != port2) {
2439 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2440 file, linenum, args[0], args[1], args[2]);
2441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
2443 }
2444
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002445 if (!port1 && !port2) {
2446 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2447 file, linenum, args[0], args[1]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451
Baptiste Assmann325137d2015-04-13 23:40:55 +02002452 newnameserver->addr = *sk;
2453 }
2454 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2455 const char *res;
2456 unsigned int time;
2457
2458 if (!*args[2]) {
2459 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2460 file, linenum, args[0]);
2461 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2466 if (res) {
2467 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2468 file, linenum, *res, args[0]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002472 if (strcmp(args[1], "nx") == 0)
2473 curr_resolvers->hold.nx = time;
2474 else if (strcmp(args[1], "other") == 0)
2475 curr_resolvers->hold.other = time;
2476 else if (strcmp(args[1], "refused") == 0)
2477 curr_resolvers->hold.refused = time;
2478 else if (strcmp(args[1], "timeout") == 0)
2479 curr_resolvers->hold.timeout = time;
2480 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002481 curr_resolvers->hold.valid = time;
2482 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002483 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2484 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488
2489 }
2490 else if (strcmp(args[0], "resolve_retries") == 0) {
2491 if (!*args[1]) {
2492 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2493 file, linenum, args[0]);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497 curr_resolvers->resolve_retries = atoi(args[1]);
2498 }
2499 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002500 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002501 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2502 file, linenum, args[0]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002506 else if (strcmp(args[1], "retry") == 0) {
2507 const char *res;
2508 unsigned int timeout_retry;
2509
2510 if (!*args[2]) {
2511 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2512 file, linenum, args[0], args[1]);
2513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
2515 }
2516 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2517 if (res) {
2518 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2519 file, linenum, *res, args[0], args[1]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523 curr_resolvers->timeout.retry = timeout_retry;
2524 }
2525 else {
2526 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2527 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
2530 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002531 } /* neither "nameserver" nor "resolvers" */
2532 else if (*args[0] != 0) {
2533 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
2536 }
2537
2538 out:
2539 free(errmsg);
2540 return err_code;
2541}
Simon Horman0d16a402015-01-30 11:22:58 +09002542
2543/*
William Lallemand51097192015-04-14 16:35:22 +02002544 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002545 * Returns the error code, 0 if OK, or any combination of :
2546 * - ERR_ABORT: must abort ASAP
2547 * - ERR_FATAL: we can continue parsing but not start the service
2548 * - ERR_WARN: a warning has been emitted
2549 * - ERR_ALERT: an alert has been emitted
2550 * Only the two first ones can stop processing, the two others are just
2551 * indicators.
2552 */
2553int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2554{
2555 static struct mailers *curmailers = NULL;
2556 struct mailer *newmailer = NULL;
2557 const char *err;
2558 int err_code = 0;
2559 char *errmsg = NULL;
2560
2561 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2562 if (!*args[1]) {
2563 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2564 err_code |= ERR_ALERT | ERR_ABORT;
2565 goto out;
2566 }
2567
2568 err = invalid_char(args[1]);
2569 if (err) {
2570 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2571 file, linenum, *err, args[0], args[1]);
2572 err_code |= ERR_ALERT | ERR_ABORT;
2573 goto out;
2574 }
2575
2576 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2577 /*
2578 * If there are two proxies with the same name only following
2579 * combinations are allowed:
2580 */
2581 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002582 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002583 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002585 }
2586 }
2587
Vincent Bernat02779b62016-04-03 13:48:43 +02002588 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2590 err_code |= ERR_ALERT | ERR_ABORT;
2591 goto out;
2592 }
2593
2594 curmailers->next = mailers;
2595 mailers = curmailers;
2596 curmailers->conf.file = strdup(file);
2597 curmailers->conf.line = linenum;
2598 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002599 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2600 * But need enough time so that timeouts don't occur
2601 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002602 }
2603 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2604 struct sockaddr_storage *sk;
2605 int port1, port2;
2606 struct protocol *proto;
2607
2608 if (!*args[2]) {
2609 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2610 file, linenum, args[0]);
2611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
2613 }
2614
2615 err = invalid_char(args[1]);
2616 if (err) {
2617 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2618 file, linenum, *err, args[1]);
2619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
2621 }
2622
Vincent Bernat02779b62016-04-03 13:48:43 +02002623 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002624 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2625 err_code |= ERR_ALERT | ERR_ABORT;
2626 goto out;
2627 }
2628
2629 /* the mailers are linked backwards first */
2630 curmailers->count++;
2631 newmailer->next = curmailers->mailer_list;
2632 curmailers->mailer_list = newmailer;
2633 newmailer->mailers = curmailers;
2634 newmailer->conf.file = strdup(file);
2635 newmailer->conf.line = linenum;
2636
2637 newmailer->id = strdup(args[1]);
2638
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002639 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002640 if (!sk) {
2641 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
2646 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002647 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2648 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002649 file, linenum, args[0], args[1]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653
2654 if (port1 != port2) {
2655 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2656 file, linenum, args[0], args[1], args[2]);
2657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
2659 }
2660
2661 if (!port1) {
2662 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2663 file, linenum, args[0], args[1], args[2]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
2668 newmailer->addr = *sk;
2669 newmailer->proto = proto;
2670 newmailer->xprt = &raw_sock;
2671 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002672 }
2673 else if (strcmp(args[0], "timeout") == 0) {
2674 if (!*args[1]) {
2675 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2676 file, linenum, args[0]);
2677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680 else if (strcmp(args[1], "mail") == 0) {
2681 const char *res;
2682 unsigned int timeout_mail;
2683 if (!*args[2]) {
2684 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2685 file, linenum, args[0], args[1]);
2686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
2689 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2690 if (res) {
2691 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2692 file, linenum, *res, args[0]);
2693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
2695 }
2696 if (timeout_mail <= 0) {
2697 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
2700 }
2701 curmailers->timeout.mail = timeout_mail;
2702 } else {
2703 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2704 file, linenum, args[0], args[1]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708 }
Simon Horman0d16a402015-01-30 11:22:58 +09002709 else if (*args[0] != 0) {
2710 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714
2715out:
2716 free(errmsg);
2717 return err_code;
2718}
2719
Simon Horman9dc49962015-01-30 11:22:59 +09002720static void free_email_alert(struct proxy *p)
2721{
2722 free(p->email_alert.mailers.name);
2723 p->email_alert.mailers.name = NULL;
2724 free(p->email_alert.from);
2725 p->email_alert.from = NULL;
2726 free(p->email_alert.to);
2727 p->email_alert.to = NULL;
2728 free(p->email_alert.myhostname);
2729 p->email_alert.myhostname = NULL;
2730}
2731
Willy Tarreau3842f002009-06-14 11:39:52 +02002732int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733{
2734 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002735 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002736 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002737 int rc;
2738 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002739 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002740 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002741 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002742 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002743 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002744
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745 if (!strcmp(args[0], "listen"))
2746 rc = PR_CAP_LISTEN;
2747 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002748 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002749 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002750 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002751 else
2752 rc = PR_CAP_NONE;
2753
2754 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 if (!*args[1]) {
2756 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002757 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002759 err_code |= ERR_ALERT | ERR_ABORT;
2760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002762
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002763 err = invalid_char(args[1]);
2764 if (err) {
2765 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2766 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002768 }
2769
Willy Tarreau8f50b682015-05-26 11:45:02 +02002770 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2771 if (curproxy) {
2772 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2773 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2774 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002776 }
2777
Vincent Bernat02779b62016-04-03 13:48:43 +02002778 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_ABORT;
2781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002783
Willy Tarreau97cb7802010-01-03 20:23:58 +01002784 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 curproxy->next = proxy;
2786 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002787 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2788 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002789 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002791 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002792 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793
William Lallemand6e62fb62015-04-28 16:55:23 +02002794 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2795 if (curproxy->cap & PR_CAP_FE)
2796 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 }
2799
2800 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002801 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002802 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002803
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002806 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002807 curproxy->no_options = defproxy.no_options;
2808 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002809 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002810 curproxy->except_net = defproxy.except_net;
2811 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002812 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002813 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002814
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002815 if (defproxy.fwdfor_hdr_len) {
2816 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2817 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2818 }
2819
Willy Tarreaub86db342009-11-30 11:50:16 +01002820 if (defproxy.orgto_hdr_len) {
2821 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2822 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2823 }
2824
Mark Lamourinec2247f02012-01-04 13:02:01 -05002825 if (defproxy.server_id_hdr_len) {
2826 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2827 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2828 }
2829
Willy Tarreau977b8e42006-12-29 14:19:17 +01002830 if (curproxy->cap & PR_CAP_FE) {
2831 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002832 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002833 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002834
2835 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002836 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2837 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002838
2839 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2840 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841
Willy Tarreau977b8e42006-12-29 14:19:17 +01002842 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002843 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002844 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002845 curproxy->fullconn = defproxy.fullconn;
2846 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002847 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002848 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002850 if (defproxy.check_req) {
2851 curproxy->check_req = calloc(1, defproxy.check_len);
2852 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002856 if (defproxy.expect_str) {
2857 curproxy->expect_str = strdup(defproxy.expect_str);
2858 if (defproxy.expect_regex) {
2859 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002860 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2861 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002862 }
2863 }
2864
Willy Tarreau67402132012-05-31 20:40:20 +02002865 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002866 if (defproxy.cookie_name)
2867 curproxy->cookie_name = strdup(defproxy.cookie_name);
2868 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002869 if (defproxy.cookie_domain)
2870 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002871
Willy Tarreau31936852010-10-06 16:59:56 +02002872 if (defproxy.cookie_maxidle)
2873 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2874
2875 if (defproxy.cookie_maxlife)
2876 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2877
Emeric Brun647caf12009-06-30 17:57:00 +02002878 if (defproxy.rdp_cookie_name)
2879 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2880 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2881
Willy Tarreau01732802007-11-01 22:48:15 +01002882 if (defproxy.url_param_name)
2883 curproxy->url_param_name = strdup(defproxy.url_param_name);
2884 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002885
Benoitaffb4812009-03-25 13:02:10 +01002886 if (defproxy.hh_name)
2887 curproxy->hh_name = strdup(defproxy.hh_name);
2888 curproxy->hh_len = defproxy.hh_len;
2889 curproxy->hh_match_domain = defproxy.hh_match_domain;
2890
Willy Tarreauef9a3602012-12-08 22:29:20 +01002891 if (defproxy.conn_src.iface_name)
2892 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2893 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002894 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002895#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002896 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002897#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002898 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002901 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902 if (defproxy.capture_name)
2903 curproxy->capture_name = strdup(defproxy.capture_name);
2904 curproxy->capture_namelen = defproxy.capture_namelen;
2905 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002909 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002910 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002911 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002912 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002913 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002914 curproxy->mon_net = defproxy.mon_net;
2915 curproxy->mon_mask = defproxy.mon_mask;
2916 if (defproxy.monitor_uri)
2917 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2918 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002919 if (defproxy.defbe.name)
2920 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002921
2922 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002923 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2924 if (curproxy->conf.logformat_string &&
2925 curproxy->conf.logformat_string != default_http_log_format &&
2926 curproxy->conf.logformat_string != default_tcp_log_format &&
2927 curproxy->conf.logformat_string != clf_http_log_format)
2928 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2929
2930 if (defproxy.conf.lfs_file) {
2931 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2932 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2933 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002934
2935 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2936 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2937 if (curproxy->conf.logformat_sd_string &&
2938 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2939 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2940
2941 if (defproxy.conf.lfsd_file) {
2942 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2943 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 }
2946
2947 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002948 curproxy->timeout.connect = defproxy.timeout.connect;
2949 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002950 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002951 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002952 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002953 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002954 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002955 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002956 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002957 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002958 }
2959
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002961 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002962
2963 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002964 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002965 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002966 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002967 LIST_INIT(&node->list);
2968 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2969 }
2970
Willy Tarreau62a61232013-04-12 18:13:46 +02002971 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2972 if (curproxy->conf.uniqueid_format_string)
2973 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2974
Dragan Dosen43885c72015-10-01 13:18:13 +02002975 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002976
Willy Tarreau62a61232013-04-12 18:13:46 +02002977 if (defproxy.conf.uif_file) {
2978 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2979 curproxy->conf.uif_line = defproxy.conf.uif_line;
2980 }
William Lallemanda73203e2012-03-12 12:48:57 +01002981
2982 /* copy default header unique id */
2983 if (defproxy.header_unique_id)
2984 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2985
William Lallemand82fe75c2012-10-23 10:25:10 +02002986 /* default compression options */
2987 if (defproxy.comp != NULL) {
2988 curproxy->comp = calloc(1, sizeof(struct comp));
2989 curproxy->comp->algos = defproxy.comp->algos;
2990 curproxy->comp->types = defproxy.comp->types;
2991 }
2992
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002994 curproxy->conf.used_listener_id = EB_ROOT;
2995 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002996
Simon Horman98637e52014-06-20 12:30:16 +09002997 if (defproxy.check_path)
2998 curproxy->check_path = strdup(defproxy.check_path);
2999 if (defproxy.check_command)
3000 curproxy->check_command = strdup(defproxy.check_command);
3001
Simon Horman9dc49962015-01-30 11:22:59 +09003002 if (defproxy.email_alert.mailers.name)
3003 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
3004 if (defproxy.email_alert.from)
3005 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
3006 if (defproxy.email_alert.to)
3007 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
3008 if (defproxy.email_alert.myhostname)
3009 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09003010 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01003011 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09003012
Willy Tarreau93893792009-07-23 13:19:11 +02003013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
3015 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
3016 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003017 /* FIXME-20070101: we should do this too at the end of the
3018 * config parsing to free all default values.
3019 */
William Lallemand6e62fb62015-04-28 16:55:23 +02003020 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
3021 err_code |= ERR_ABORT;
3022 goto out;
3023 }
3024
Willy Tarreaua534fea2008-08-03 12:19:50 +02003025 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003026 free(defproxy.check_command);
3027 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003028 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003029 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003030 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003031 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003032 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003033 free(defproxy.capture_name);
3034 free(defproxy.monitor_uri);
3035 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003036 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003037 free(defproxy.fwdfor_hdr_name);
3038 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003039 free(defproxy.orgto_hdr_name);
3040 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003041 free(defproxy.server_id_hdr_name);
3042 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003043 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003044 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003045 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003046 free(defproxy.expect_regex);
3047 defproxy.expect_regex = NULL;
3048 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003049
Willy Tarreau62a61232013-04-12 18:13:46 +02003050 if (defproxy.conf.logformat_string != default_http_log_format &&
3051 defproxy.conf.logformat_string != default_tcp_log_format &&
3052 defproxy.conf.logformat_string != clf_http_log_format)
3053 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003054
Willy Tarreau62a61232013-04-12 18:13:46 +02003055 free(defproxy.conf.uniqueid_format_string);
3056 free(defproxy.conf.lfs_file);
3057 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003058 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003059 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003060
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003061 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3062 free(defproxy.conf.logformat_sd_string);
3063 free(defproxy.conf.lfsd_file);
3064
Willy Tarreaua534fea2008-08-03 12:19:50 +02003065 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003066 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003067
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 /* we cannot free uri_auth because it might already be used */
3069 init_default_instance();
3070 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003071 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3072 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 }
3076 else if (curproxy == NULL) {
3077 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003081
3082 /* update the current file and line being parsed */
3083 curproxy->conf.args.file = curproxy->conf.file;
3084 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003085
3086 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003087 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3088 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3089 if (err_code & ERR_FATAL)
3090 goto out;
3091 }
3092 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003093 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003094 int cur_arg;
3095
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 if (curproxy == &defproxy) {
3097 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003101 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103
Willy Tarreau24709282013-03-10 21:32:12 +01003104 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003105 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003110
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003111 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003112
3113 /* use default settings for unix sockets */
3114 bind_conf->ux.uid = global.unix_bind.ux.uid;
3115 bind_conf->ux.gid = global.unix_bind.ux.gid;
3116 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003117
3118 /* NOTE: the following line might create several listeners if there
3119 * are comma-separated IPs or port ranges. So all further processing
3120 * will have to be applied to all listeners created after last_listen.
3121 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003122 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3123 if (errmsg && *errmsg) {
3124 indent_msg(&errmsg, 2);
3125 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003126 }
3127 else
3128 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3129 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003133
Willy Tarreau4348fad2012-09-20 16:48:07 +02003134 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3135 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003136 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003137 }
3138
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003139 cur_arg = 2;
3140 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003141 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003142 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003143 char *err;
3144
Willy Tarreau26982662012-09-12 23:17:10 +02003145 kw = bind_find_kw(args[cur_arg]);
3146 if (kw) {
3147 char *err = NULL;
3148 int code;
3149
3150 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003151 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3152 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003153 cur_arg += 1 + kw->skip ;
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157
Willy Tarreau4348fad2012-09-20 16:48:07 +02003158 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003159 err_code |= code;
3160
3161 if (code) {
3162 if (err && *err) {
3163 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003164 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003165 }
3166 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003167 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3168 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003169 if (code & ERR_FATAL) {
3170 free(err);
3171 cur_arg += 1 + kw->skip;
3172 goto out;
3173 }
3174 }
3175 free(err);
3176 cur_arg += 1 + kw->skip;
3177 continue;
3178 }
3179
Willy Tarreau8638f482012-09-18 18:01:17 +02003180 err = NULL;
3181 if (!bind_dumped) {
3182 bind_dump_kws(&err);
3183 indent_msg(&err, 4);
3184 bind_dumped = 1;
3185 }
3186
3187 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3188 file, linenum, args[0], args[1], args[cur_arg],
3189 err ? " Registered keywords :" : "", err ? err : "");
3190 free(err);
3191
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003194 }
Willy Tarreau93893792009-07-23 13:19:11 +02003195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003198 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3200 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003204 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003206
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 /* flush useless bits */
3208 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003211 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003212 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003214
William Lallemanddf1425a2015-04-28 20:17:49 +02003215 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3216 goto out;
3217
Willy Tarreau1c47f852006-07-09 08:22:27 +02003218 if (!*args[1]) {
3219 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003223 }
3224
Willy Tarreaua534fea2008-08-03 12:19:50 +02003225 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003226 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003227 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003228 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003229 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3230
Willy Tarreau93893792009-07-23 13:19:11 +02003231 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003234 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3235 goto out;
3236
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3238 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3239 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3240 else {
3241 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
3245 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003246 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003247 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003248
3249 if (curproxy == &defproxy) {
3250 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3251 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003254 }
3255
William Lallemanddf1425a2015-04-28 20:17:49 +02003256 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3257 goto out;
3258
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003259 if (!*args[1]) {
3260 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3261 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003264 }
3265
3266 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003267 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003268 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003269
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003270 if (curproxy->uuid <= 0) {
3271 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003272 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003275 }
3276
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003277 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3278 if (node) {
3279 struct proxy *target = container_of(node, struct proxy, conf.id);
3280 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3281 file, linenum, proxy_type_str(curproxy), curproxy->id,
3282 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285 }
3286 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003287 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003288 else if (!strcmp(args[0], "description")) {
3289 int i, len=0;
3290 char *d;
3291
Cyril Bonté99ed3272010-01-24 23:29:44 +01003292 if (curproxy == &defproxy) {
3293 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3294 file, linenum, args[0]);
3295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
3297 }
3298
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003299 if (!*args[1]) {
3300 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3301 file, linenum, args[0]);
3302 return -1;
3303 }
3304
Willy Tarreau348acfe2014-04-14 15:00:39 +02003305 for (i = 1; *args[i]; i++)
3306 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003307
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003308 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003309 curproxy->desc = d;
3310
Willy Tarreau348acfe2014-04-14 15:00:39 +02003311 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3312 for (i = 2; *args[i]; i++)
3313 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003314
3315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003317 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 curproxy->state = PR_STSTOPPED;
3320 }
3321 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003322 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 curproxy->state = PR_STNEW;
3325 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003326 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3327 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003328 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003329
3330 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003331 unsigned int low, high;
3332
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003333 if (strcmp(args[cur_arg], "all") == 0) {
3334 set = 0;
3335 break;
3336 }
3337 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003338 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003339 }
3340 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003341 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003342 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003343 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003344 char *dash = strchr(args[cur_arg], '-');
3345
3346 low = high = str2uic(args[cur_arg]);
3347 if (dash)
3348 high = str2uic(dash + 1);
3349
3350 if (high < low) {
3351 unsigned int swap = low;
3352 low = high;
3353 high = swap;
3354 }
3355
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003356 if (low < 1 || high > LONGBITS) {
3357 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3358 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003361 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003362 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003363 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003364 }
3365 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003366 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3367 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003370 }
3371 cur_arg++;
3372 }
3373 curproxy->bind_proc = set;
3374 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003375 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003376 if (curproxy == &defproxy) {
3377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003380 }
3381
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003382 err = invalid_char(args[1]);
3383 if (err) {
3384 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3385 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003387 }
3388
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003389 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003390 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3391 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003394 }
3395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3397 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398
Willy Tarreau977b8e42006-12-29 14:19:17 +01003399 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003401
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 if (*(args[1]) == 0) {
3403 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3404 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003408
Willy Tarreau67402132012-05-31 20:40:20 +02003409 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003410 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003411 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003412 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 curproxy->cookie_name = strdup(args[1]);
3414 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003415
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 cur_arg = 2;
3417 while (*(args[cur_arg])) {
3418 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003419 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 }
3421 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003422 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 }
3424 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003425 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 }
3427 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003428 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 }
3430 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003431 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003433 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003434 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003437 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003439 else if (!strcmp(args[cur_arg], "httponly")) {
3440 curproxy->ck_opts |= PR_CK_HTTPONLY;
3441 }
3442 else if (!strcmp(args[cur_arg], "secure")) {
3443 curproxy->ck_opts |= PR_CK_SECURE;
3444 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003445 else if (!strcmp(args[cur_arg], "domain")) {
3446 if (!*args[cur_arg + 1]) {
3447 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3448 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003451 }
3452
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003453 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003454 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003455 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3456 " dots nor does not start with a dot."
3457 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003458 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003459 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003460 }
3461
3462 err = invalid_domainchar(args[cur_arg + 1]);
3463 if (err) {
3464 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3465 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003468 }
3469
Willy Tarreau68a897b2009-12-03 23:28:34 +01003470 if (!curproxy->cookie_domain) {
3471 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3472 } else {
3473 /* one domain was already specified, add another one by
3474 * building the string which will be returned along with
3475 * the cookie.
3476 */
3477 char *new_ptr;
3478 int new_len = strlen(curproxy->cookie_domain) +
3479 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3480 new_ptr = malloc(new_len);
3481 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3482 free(curproxy->cookie_domain);
3483 curproxy->cookie_domain = new_ptr;
3484 }
Willy Tarreau31936852010-10-06 16:59:56 +02003485 cur_arg++;
3486 }
3487 else if (!strcmp(args[cur_arg], "maxidle")) {
3488 unsigned int maxidle;
3489 const char *res;
3490
3491 if (!*args[cur_arg + 1]) {
3492 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3493 file, linenum, args[cur_arg]);
3494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
3496 }
3497
3498 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3499 if (res) {
3500 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3501 file, linenum, *res, args[cur_arg]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
3505 curproxy->cookie_maxidle = maxidle;
3506 cur_arg++;
3507 }
3508 else if (!strcmp(args[cur_arg], "maxlife")) {
3509 unsigned int maxlife;
3510 const char *res;
3511
3512 if (!*args[cur_arg + 1]) {
3513 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3514 file, linenum, args[cur_arg]);
3515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
3517 }
3518
3519 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3520 if (res) {
3521 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3522 file, linenum, *res, args[cur_arg]);
3523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
3525 }
3526 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003527 cur_arg++;
3528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003530 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 +02003531 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 }
3535 cur_arg++;
3536 }
Willy Tarreau67402132012-05-31 20:40:20 +02003537 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3539 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 }
3542
Willy Tarreau67402132012-05-31 20:40:20 +02003543 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3545 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003548
Willy Tarreau67402132012-05-31 20:40:20 +02003549 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003550 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3551 file, linenum);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003555 else if (!strcmp(args[0], "email-alert")) {
3556 if (*(args[1]) == 0) {
3557 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3558 file, linenum, args[0]);
3559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
3561 }
3562
3563 if (!strcmp(args[1], "from")) {
3564 if (*(args[1]) == 0) {
3565 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3566 file, linenum, args[1]);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
3570 free(curproxy->email_alert.from);
3571 curproxy->email_alert.from = strdup(args[2]);
3572 }
3573 else if (!strcmp(args[1], "mailers")) {
3574 if (*(args[1]) == 0) {
3575 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3576 file, linenum, args[1]);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
3580 free(curproxy->email_alert.mailers.name);
3581 curproxy->email_alert.mailers.name = strdup(args[2]);
3582 }
3583 else if (!strcmp(args[1], "myhostname")) {
3584 if (*(args[1]) == 0) {
3585 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3586 file, linenum, args[1]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590 free(curproxy->email_alert.myhostname);
3591 curproxy->email_alert.myhostname = strdup(args[2]);
3592 }
Simon Horman64e34162015-02-06 11:11:57 +09003593 else if (!strcmp(args[1], "level")) {
3594 curproxy->email_alert.level = get_log_level(args[2]);
3595 if (curproxy->email_alert.level < 0) {
3596 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3597 file, linenum, args[1], args[2]);
3598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
3600 }
3601 }
Simon Horman9dc49962015-01-30 11:22:59 +09003602 else if (!strcmp(args[1], "to")) {
3603 if (*(args[1]) == 0) {
3604 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3605 file, linenum, args[1]);
3606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
3608 }
3609 free(curproxy->email_alert.to);
3610 curproxy->email_alert.to = strdup(args[2]);
3611 }
3612 else {
3613 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3614 file, linenum, args[1]);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
3617 }
Simon Horman64e34162015-02-06 11:11:57 +09003618 /* Indicate that the email_alert is at least partially configured */
3619 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003620 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003621 else if (!strcmp(args[0], "external-check")) {
3622 if (*(args[1]) == 0) {
3623 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3624 file, linenum, args[0]);
3625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
3627 }
3628
3629 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003630 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003631 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003632 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003633 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3634 file, linenum, args[1]);
3635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
3637 }
3638 free(curproxy->check_command);
3639 curproxy->check_command = strdup(args[2]);
3640 }
3641 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003642 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003643 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003644 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003645 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3646 file, linenum, args[1]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650 free(curproxy->check_path);
3651 curproxy->check_path = strdup(args[2]);
3652 }
3653 else {
3654 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3655 file, linenum, args[1]);
3656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
3658 }
3659 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003660 else if (!strcmp(args[0], "persist")) { /* persist */
3661 if (*(args[1]) == 0) {
3662 Alert("parsing [%s:%d] : missing persist method.\n",
3663 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003666 }
3667
3668 if (!strncmp(args[1], "rdp-cookie", 10)) {
3669 curproxy->options2 |= PR_O2_RDPC_PRST;
3670
Emeric Brunb982a3d2010-01-04 15:45:53 +01003671 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003672 const char *beg, *end;
3673
3674 beg = args[1] + 11;
3675 end = strchr(beg, ')');
3676
William Lallemanddf1425a2015-04-28 20:17:49 +02003677 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3678 goto out;
3679
Emeric Brun647caf12009-06-30 17:57:00 +02003680 if (!end || end == beg) {
3681 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3682 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003685 }
3686
3687 free(curproxy->rdp_cookie_name);
3688 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3689 curproxy->rdp_cookie_len = end-beg;
3690 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003691 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003692 free(curproxy->rdp_cookie_name);
3693 curproxy->rdp_cookie_name = strdup("msts");
3694 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3695 }
3696 else { /* syntax */
3697 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3698 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003701 }
3702 }
3703 else {
3704 Alert("parsing [%s:%d] : unknown persist method.\n",
3705 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003708 }
3709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003711 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003715 else if (!strcmp(args[0], "load-server-state-from-file")) {
3716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3717 err_code |= ERR_WARN;
3718 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3719 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3720 }
3721 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3722 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3723 }
3724 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3725 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3726 }
3727 else {
3728 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3729 file, linenum, args[0], args[1]);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733 }
3734 else if (!strcmp(args[0], "server-state-file-name")) {
3735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3736 err_code |= ERR_WARN;
3737 if (*(args[1]) == 0) {
3738 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3739 file, linenum, args[0]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743 else if (!strcmp(args[1], "use-backend-name"))
3744 curproxy->server_state_file_name = strdup(curproxy->id);
3745 else
3746 curproxy->server_state_file_name = strdup(args[1]);
3747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003751
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003753 if (curproxy == &defproxy) {
3754 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
3757 }
3758
William Lallemand1a748ae2015-05-19 16:37:23 +02003759 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3760 goto out;
3761
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 if (*(args[4]) == 0) {
3763 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3764 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003768 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 curproxy->capture_name = strdup(args[2]);
3770 curproxy->capture_namelen = strlen(curproxy->capture_name);
3771 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 curproxy->to_log |= LW_COOKIE;
3773 }
3774 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3775 struct cap_hdr *hdr;
3776
3777 if (curproxy == &defproxy) {
3778 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 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
3782
William Lallemand1a748ae2015-05-19 16:37:23 +02003783 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3784 goto out;
3785
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3787 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3788 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 }
3792
Vincent Bernat02779b62016-04-03 13:48:43 +02003793 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 hdr->next = curproxy->req_cap;
3795 hdr->name = strdup(args[3]);
3796 hdr->namelen = strlen(args[3]);
3797 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003798 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 hdr->index = curproxy->nb_req_cap++;
3800 curproxy->req_cap = hdr;
3801 curproxy->to_log |= LW_REQHDR;
3802 }
3803 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3804 struct cap_hdr *hdr;
3805
3806 if (curproxy == &defproxy) {
3807 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 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
3811
William Lallemand1a748ae2015-05-19 16:37:23 +02003812 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3813 goto out;
3814
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3816 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3817 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003821 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 hdr->next = curproxy->rsp_cap;
3823 hdr->name = strdup(args[3]);
3824 hdr->namelen = strlen(args[3]);
3825 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003826 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 hdr->index = curproxy->nb_rsp_cap++;
3828 curproxy->rsp_cap = hdr;
3829 curproxy->to_log |= LW_RSPHDR;
3830 }
3831 else {
3832 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3833 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 }
3837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003839 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003841
William Lallemanddf1425a2015-04-28 20:17:49 +02003842 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3843 goto out;
3844
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 if (*(args[1]) == 0) {
3846 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3847 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
3851 curproxy->conn_retries = atol(args[1]);
3852 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003853 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003854 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003855
3856 if (curproxy == &defproxy) {
3857 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861
Willy Tarreau20b0de52012-12-24 15:45:22 +01003862 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003863 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003864 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3865 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3866 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3867 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003868 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 +01003869 file, linenum, args[0]);
3870 err_code |= ERR_WARN;
3871 }
3872
Willy Tarreauff011f22011-01-06 17:51:27 +01003873 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003874
Willy Tarreauff011f22011-01-06 17:51:27 +01003875 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003876 err_code |= ERR_ALERT | ERR_ABORT;
3877 goto out;
3878 }
3879
Willy Tarreau5002f572014-04-23 01:32:02 +02003880 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003881 err_code |= warnif_cond_conflicts(rule->cond,
3882 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3883 file, linenum);
3884
Willy Tarreauff011f22011-01-06 17:51:27 +01003885 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003886 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003887 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003888 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003889
3890 if (curproxy == &defproxy) {
3891 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
3896 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003897 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003898 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3899 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003900 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3901 file, linenum, args[0]);
3902 err_code |= ERR_WARN;
3903 }
3904
3905 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3906
3907 if (!rule) {
3908 err_code |= ERR_ALERT | ERR_ABORT;
3909 goto out;
3910 }
3911
3912 err_code |= warnif_cond_conflicts(rule->cond,
3913 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3914 file, linenum);
3915
3916 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3917 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003918 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3919 /* set the header name and length into the proxy structure */
3920 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3921 err_code |= ERR_WARN;
3922
3923 if (!*args[1]) {
3924 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3925 file, linenum, args[0]);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929
3930 /* set the desired header name */
3931 free(curproxy->server_id_hdr_name);
3932 curproxy->server_id_hdr_name = strdup(args[1]);
3933 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3934 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003935 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003936 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003937
Willy Tarreaub099aca2008-10-12 17:26:37 +02003938 if (curproxy == &defproxy) {
3939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003942 }
3943
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003944 /* emulate "block" using "http-request block". Since these rules are supposed to
3945 * be processed before all http-request rules, we put them into their own list
3946 * and will insert them at the end.
3947 */
3948 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3949 if (!rule) {
3950 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003951 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003952 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003953 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3954 err_code |= warnif_cond_conflicts(rule->cond,
3955 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3956 file, linenum);
3957 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003958
3959 if (!already_warned(WARN_BLOCK_DEPRECATED))
3960 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]);
3961
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003962 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003963 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003964 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003965
Cyril Bonté99ed3272010-01-24 23:29:44 +01003966 if (curproxy == &defproxy) {
3967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
3971
Willy Tarreaube4653b2015-05-28 15:26:58 +02003972 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003973 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3974 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003977 }
3978
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003979 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003980 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003981 err_code |= warnif_cond_conflicts(rule->cond,
3982 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3983 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003984 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003985 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003986 struct switching_rule *rule;
3987
Willy Tarreaub099aca2008-10-12 17:26:37 +02003988 if (curproxy == &defproxy) {
3989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003992 }
3993
Willy Tarreau55ea7572007-06-17 19:56:27 +02003994 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003996
3997 if (*(args[1]) == 0) {
3998 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004001 }
4002
Willy Tarreauf51658d2014-04-23 01:21:56 +02004003 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
4004 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4005 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4006 file, linenum, errmsg);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004010
Willy Tarreauf51658d2014-04-23 01:21:56 +02004011 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004012 }
4013
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004014 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02004015 rule->cond = cond;
4016 rule->be.name = strdup(args[1]);
4017 LIST_INIT(&rule->list);
4018 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4019 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004020 else if (strcmp(args[0], "use-server") == 0) {
4021 struct server_rule *rule;
4022
4023 if (curproxy == &defproxy) {
4024 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028
4029 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4030 err_code |= ERR_WARN;
4031
4032 if (*(args[1]) == 0) {
4033 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037
4038 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4039 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4040 file, linenum, args[0]);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004045 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4046 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4047 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
4050 }
4051
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004052 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004053
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004054 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004055 rule->cond = cond;
4056 rule->srv.name = strdup(args[1]);
4057 LIST_INIT(&rule->list);
4058 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4059 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4060 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004061 else if ((!strcmp(args[0], "force-persist")) ||
4062 (!strcmp(args[0], "ignore-persist"))) {
4063 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004064
4065 if (curproxy == &defproxy) {
4066 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070
4071 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4072 err_code |= ERR_WARN;
4073
Willy Tarreauef6494c2010-01-28 17:12:36 +01004074 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004075 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4076 file, linenum, args[0]);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004081 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4082 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4083 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004088 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4089 * where force-persist is applied.
4090 */
4091 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004092
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004093 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004094 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004095 if (!strcmp(args[0], "force-persist")) {
4096 rule->type = PERSIST_TYPE_FORCE;
4097 } else {
4098 rule->type = PERSIST_TYPE_IGNORE;
4099 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004100 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004101 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004102 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004103 else if (!strcmp(args[0], "stick-table")) {
4104 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004105 struct proxy *other;
4106
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004107 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004108 if (other) {
4109 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4110 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
4113 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004114
Emeric Brun32da3c42010-09-23 18:39:19 +02004115 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004116 curproxy->table.type = (unsigned int)-1;
4117 while (*args[myidx]) {
4118 const char *err;
4119
4120 if (strcmp(args[myidx], "size") == 0) {
4121 myidx++;
4122 if (!*(args[myidx])) {
4123 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4124 file, linenum, args[myidx-1]);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4129 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4130 file, linenum, *err, args[myidx-1]);
4131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
4133 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004134 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004135 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004136 else if (strcmp(args[myidx], "peers") == 0) {
4137 myidx++;
Godbach50523162013-12-11 19:48:57 +08004138 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004139 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4140 file, linenum, args[myidx-1]);
4141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
Godbach50523162013-12-11 19:48:57 +08004143 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004144 curproxy->table.peers.name = strdup(args[myidx++]);
4145 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004146 else if (strcmp(args[myidx], "expire") == 0) {
4147 myidx++;
4148 if (!*(args[myidx])) {
4149 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4150 file, linenum, args[myidx-1]);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4155 if (err) {
4156 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4157 file, linenum, *err, args[myidx-1]);
4158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
4160 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004161 if (val > INT_MAX) {
4162 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4163 file, linenum, val);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004167 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004168 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004169 }
4170 else if (strcmp(args[myidx], "nopurge") == 0) {
4171 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004172 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004173 }
4174 else if (strcmp(args[myidx], "type") == 0) {
4175 myidx++;
4176 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4177 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4178 file, linenum, args[myidx]);
4179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
4181 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004182 /* myidx already points to next arg */
4183 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004184 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004185 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004186 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004187
4188 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004189 nw = args[myidx];
4190 while (*nw) {
4191 /* the "store" keyword supports a comma-separated list */
4192 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004193 sa = NULL; /* store arg */
4194 while (*nw && *nw != ',') {
4195 if (*nw == '(') {
4196 *nw = 0;
4197 sa = ++nw;
4198 while (*nw != ')') {
4199 if (!*nw) {
4200 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4201 file, linenum, args[0], cw);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
4205 nw++;
4206 }
4207 *nw = '\0';
4208 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004209 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004210 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004211 if (*nw)
4212 *nw++ = '\0';
4213 type = stktable_get_data_type(cw);
4214 if (type < 0) {
4215 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4216 file, linenum, args[0], cw);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
Willy Tarreauac782882010-06-20 10:41:54 +02004220
4221 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4222 switch (err) {
4223 case PE_NONE: break;
4224 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004225 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4226 file, linenum, args[0], cw);
4227 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004228 break;
4229
4230 case PE_ARG_MISSING:
4231 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4232 file, linenum, args[0], cw);
4233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
4235
4236 case PE_ARG_NOT_USED:
4237 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4238 file, linenum, args[0], cw);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
4241
4242 default:
4243 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4244 file, linenum, args[0], cw);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004247 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004248 }
4249 myidx++;
4250 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004251 else {
4252 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4253 file, linenum, args[myidx]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004256 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004257 }
4258
4259 if (!curproxy->table.size) {
4260 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4261 file, linenum);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265
4266 if (curproxy->table.type == (unsigned int)-1) {
4267 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4268 file, linenum);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272 }
4273 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004274 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004275 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004276 int myidx = 0;
4277 const char *name = NULL;
4278 int flags;
4279
4280 if (curproxy == &defproxy) {
4281 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
4285
4286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4287 err_code |= ERR_WARN;
4288 goto out;
4289 }
4290
4291 myidx++;
4292 if ((strcmp(args[myidx], "store") == 0) ||
4293 (strcmp(args[myidx], "store-request") == 0)) {
4294 myidx++;
4295 flags = STK_IS_STORE;
4296 }
4297 else if (strcmp(args[myidx], "store-response") == 0) {
4298 myidx++;
4299 flags = STK_IS_STORE | STK_ON_RSP;
4300 }
4301 else if (strcmp(args[myidx], "match") == 0) {
4302 myidx++;
4303 flags = STK_IS_MATCH;
4304 }
4305 else if (strcmp(args[myidx], "on") == 0) {
4306 myidx++;
4307 flags = STK_IS_MATCH | STK_IS_STORE;
4308 }
4309 else {
4310 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
4313 }
4314
4315 if (*(args[myidx]) == 0) {
4316 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4317 err_code |= ERR_ALERT | ERR_FATAL;
4318 goto out;
4319 }
4320
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004321 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004322 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004323 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004324 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
4327 }
4328
4329 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004330 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4331 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4332 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004333 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004334 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004335 goto out;
4336 }
4337 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004338 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4339 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4340 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004341 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004342 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004343 goto out;
4344 }
4345 }
4346
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004347 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004348 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004349
Emeric Brunb982a3d2010-01-04 15:45:53 +01004350 if (strcmp(args[myidx], "table") == 0) {
4351 myidx++;
4352 name = args[myidx++];
4353 }
4354
Willy Tarreauef6494c2010-01-28 17:12:36 +01004355 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004356 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4357 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4358 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004359 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004360 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004361 goto out;
4362 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004363 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004364 else if (*(args[myidx])) {
4365 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4366 file, linenum, args[0], args[myidx]);
4367 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004368 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004369 goto out;
4370 }
Emeric Brun97679e72010-09-23 17:56:44 +02004371 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004372 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004373 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004374 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004375
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004376 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004377 rule->cond = cond;
4378 rule->expr = expr;
4379 rule->flags = flags;
4380 rule->table.name = name ? strdup(name) : NULL;
4381 LIST_INIT(&rule->list);
4382 if (flags & STK_ON_RSP)
4383 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4384 else
4385 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 else if (!strcmp(args[0], "stats")) {
4388 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4389 curproxy->uri_auth = NULL; /* we must detach from the default config */
4390
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004391 if (!*args[1]) {
4392 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004393 } else if (!strcmp(args[1], "admin")) {
4394 struct stats_admin_rule *rule;
4395
4396 if (curproxy == &defproxy) {
4397 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401
4402 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4403 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4404 err_code |= ERR_ALERT | ERR_ABORT;
4405 goto out;
4406 }
4407
4408 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4409 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4410 file, linenum, args[0], args[1]);
4411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
4413 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004414 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4415 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4416 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
4420
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004421 err_code |= warnif_cond_conflicts(cond,
4422 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4423 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004424
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004425 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004426 rule->cond = cond;
4427 LIST_INIT(&rule->list);
4428 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004429 } else if (!strcmp(args[1], "uri")) {
4430 if (*(args[2]) == 0) {
4431 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004432 err_code |= ERR_ALERT | ERR_FATAL;
4433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004434 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4435 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_ABORT;
4437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 }
4439 } else if (!strcmp(args[1], "realm")) {
4440 if (*(args[2]) == 0) {
4441 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4445 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_ABORT;
4447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004449 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004450 unsigned interval;
4451
4452 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4453 if (err) {
4454 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4455 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004458 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4459 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_ABORT;
4461 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004462 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004463 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004464 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004465
4466 if (curproxy == &defproxy) {
4467 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
4470 }
4471
4472 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4473 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4474 err_code |= ERR_ALERT | ERR_ABORT;
4475 goto out;
4476 }
4477
Willy Tarreauff011f22011-01-06 17:51:27 +01004478 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004479 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004480 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4481 file, linenum, args[0]);
4482 err_code |= ERR_WARN;
4483 }
4484
Willy Tarreauff011f22011-01-06 17:51:27 +01004485 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004486
Willy Tarreauff011f22011-01-06 17:51:27 +01004487 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004488 err_code |= ERR_ALERT | ERR_ABORT;
4489 goto out;
4490 }
4491
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004492 err_code |= warnif_cond_conflicts(rule->cond,
4493 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4494 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004495 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004496
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 } else if (!strcmp(args[1], "auth")) {
4498 if (*(args[2]) == 0) {
4499 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
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 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_ABORT;
4505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
4507 } else if (!strcmp(args[1], "scope")) {
4508 if (*(args[2]) == 0) {
4509 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4513 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004514 err_code |= ERR_ALERT | ERR_ABORT;
4515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 }
4517 } else if (!strcmp(args[1], "enable")) {
4518 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4519 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004520 err_code |= ERR_ALERT | ERR_ABORT;
4521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004523 } else if (!strcmp(args[1], "hide-version")) {
4524 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4525 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004526 err_code |= ERR_ALERT | ERR_ABORT;
4527 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004528 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004529 } else if (!strcmp(args[1], "show-legends")) {
4530 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4531 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4532 err_code |= ERR_ALERT | ERR_ABORT;
4533 goto out;
4534 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004535 } else if (!strcmp(args[1], "show-node")) {
4536
4537 if (*args[2]) {
4538 int i;
4539 char c;
4540
4541 for (i=0; args[2][i]; i++) {
4542 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004543 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4544 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004545 break;
4546 }
4547
4548 if (!i || args[2][i]) {
4549 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4550 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4551 file, linenum, args[0], args[1]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555 }
4556
4557 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4558 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4559 err_code |= ERR_ALERT | ERR_ABORT;
4560 goto out;
4561 }
4562 } else if (!strcmp(args[1], "show-desc")) {
4563 char *desc = NULL;
4564
4565 if (*args[2]) {
4566 int i, len=0;
4567 char *d;
4568
Willy Tarreau348acfe2014-04-14 15:00:39 +02004569 for (i = 2; *args[i]; i++)
4570 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004571
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004572 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004573
Willy Tarreau348acfe2014-04-14 15:00:39 +02004574 d += snprintf(d, desc + len - d, "%s", args[2]);
4575 for (i = 3; *args[i]; i++)
4576 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004577 }
4578
4579 if (!*args[2] && !global.desc)
4580 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4581 file, linenum, args[1]);
4582 else {
4583 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4584 free(desc);
4585 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4586 err_code |= ERR_ALERT | ERR_ABORT;
4587 goto out;
4588 }
4589 free(desc);
4590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004592stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004593 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 +01004594 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 }
4598 }
4599 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004600 int optnum;
4601
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004602 if (*(args[1]) == '\0') {
4603 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004608
4609 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4610 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004611 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4612 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4613 file, linenum, cfg_opts[optnum].name);
4614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004617 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4618 goto out;
4619
Willy Tarreau93893792009-07-23 13:19:11 +02004620 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4621 err_code |= ERR_WARN;
4622 goto out;
4623 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004624
Willy Tarreau3842f002009-06-14 11:39:52 +02004625 curproxy->no_options &= ~cfg_opts[optnum].val;
4626 curproxy->options &= ~cfg_opts[optnum].val;
4627
4628 switch (kwm) {
4629 case KWM_STD:
4630 curproxy->options |= cfg_opts[optnum].val;
4631 break;
4632 case KWM_NO:
4633 curproxy->no_options |= cfg_opts[optnum].val;
4634 break;
4635 case KWM_DEF: /* already cleared */
4636 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004637 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004638
Willy Tarreau93893792009-07-23 13:19:11 +02004639 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004640 }
4641 }
4642
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004643 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4644 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004645 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4646 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4647 file, linenum, cfg_opts2[optnum].name);
4648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
4650 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004651 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4652 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004653 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4654 err_code |= ERR_WARN;
4655 goto out;
4656 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004657
Willy Tarreau3842f002009-06-14 11:39:52 +02004658 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4659 curproxy->options2 &= ~cfg_opts2[optnum].val;
4660
4661 switch (kwm) {
4662 case KWM_STD:
4663 curproxy->options2 |= cfg_opts2[optnum].val;
4664 break;
4665 case KWM_NO:
4666 curproxy->no_options2 |= cfg_opts2[optnum].val;
4667 break;
4668 case KWM_DEF: /* already cleared */
4669 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004670 }
Willy Tarreau93893792009-07-23 13:19:11 +02004671 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004672 }
4673 }
4674
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004675 /* HTTP options override each other. They can be cancelled using
4676 * "no option xxx" which only switches to default mode if the mode
4677 * was this one (useful for cancelling options set in defaults
4678 * sections).
4679 */
4680 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004681 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4682 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004683 if (kwm == KWM_STD) {
4684 curproxy->options &= ~PR_O_HTTP_MODE;
4685 curproxy->options |= PR_O_HTTP_PCL;
4686 goto out;
4687 }
4688 else if (kwm == KWM_NO) {
4689 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4690 curproxy->options &= ~PR_O_HTTP_MODE;
4691 goto out;
4692 }
4693 }
4694 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004695 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4696 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004697 if (kwm == KWM_STD) {
4698 curproxy->options &= ~PR_O_HTTP_MODE;
4699 curproxy->options |= PR_O_HTTP_FCL;
4700 goto out;
4701 }
4702 else if (kwm == KWM_NO) {
4703 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4704 curproxy->options &= ~PR_O_HTTP_MODE;
4705 goto out;
4706 }
4707 }
4708 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004709 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4710 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004711 if (kwm == KWM_STD) {
4712 curproxy->options &= ~PR_O_HTTP_MODE;
4713 curproxy->options |= PR_O_HTTP_SCL;
4714 goto out;
4715 }
4716 else if (kwm == KWM_NO) {
4717 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4718 curproxy->options &= ~PR_O_HTTP_MODE;
4719 goto out;
4720 }
4721 }
4722 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004723 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4724 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004725 if (kwm == KWM_STD) {
4726 curproxy->options &= ~PR_O_HTTP_MODE;
4727 curproxy->options |= PR_O_HTTP_KAL;
4728 goto out;
4729 }
4730 else if (kwm == KWM_NO) {
4731 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4732 curproxy->options &= ~PR_O_HTTP_MODE;
4733 goto out;
4734 }
4735 }
4736 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004737 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4738 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004739 if (kwm == KWM_STD) {
4740 curproxy->options &= ~PR_O_HTTP_MODE;
4741 curproxy->options |= PR_O_HTTP_TUN;
4742 goto out;
4743 }
4744 else if (kwm == KWM_NO) {
4745 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4746 curproxy->options &= ~PR_O_HTTP_MODE;
4747 goto out;
4748 }
4749 }
4750
Joseph Lynch726ab712015-05-11 23:25:34 -07004751 /* Redispatch can take an integer argument that control when the
4752 * resispatch occurs. All values are relative to the retries option.
4753 * This can be cancelled using "no option xxx".
4754 */
4755 if (strcmp(args[1], "redispatch") == 0) {
4756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4757 err_code |= ERR_WARN;
4758 goto out;
4759 }
4760
4761 curproxy->no_options &= ~PR_O_REDISP;
4762 curproxy->options &= ~PR_O_REDISP;
4763
4764 switch (kwm) {
4765 case KWM_STD:
4766 curproxy->options |= PR_O_REDISP;
4767 curproxy->redispatch_after = -1;
4768 if(*args[2]) {
4769 curproxy->redispatch_after = atol(args[2]);
4770 }
4771 break;
4772 case KWM_NO:
4773 curproxy->no_options |= PR_O_REDISP;
4774 curproxy->redispatch_after = 0;
4775 break;
4776 case KWM_DEF: /* already cleared */
4777 break;
4778 }
4779 goto out;
4780 }
4781
Willy Tarreau3842f002009-06-14 11:39:52 +02004782 if (kwm != KWM_STD) {
4783 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004784 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004787 }
4788
Emeric Brun3a058f32009-06-30 18:26:00 +02004789 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004790 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004792 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004793 if (*(args[2]) != '\0') {
4794 if (!strcmp(args[2], "clf")) {
4795 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004796 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004797 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004798 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004801 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004802 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4803 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004804 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004805 if (curproxy->conf.logformat_string != default_http_log_format &&
4806 curproxy->conf.logformat_string != default_tcp_log_format &&
4807 curproxy->conf.logformat_string != clf_http_log_format)
4808 free(curproxy->conf.logformat_string);
4809 curproxy->conf.logformat_string = logformat;
4810
4811 free(curproxy->conf.lfs_file);
4812 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4813 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004814 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004815 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004816 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004817 if (curproxy->conf.logformat_string != default_http_log_format &&
4818 curproxy->conf.logformat_string != default_tcp_log_format &&
4819 curproxy->conf.logformat_string != clf_http_log_format)
4820 free(curproxy->conf.logformat_string);
4821 curproxy->conf.logformat_string = default_tcp_log_format;
4822
4823 free(curproxy->conf.lfs_file);
4824 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4825 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004826
4827 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4828 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004829 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004831 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004832 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004834
William Lallemanddf1425a2015-04-28 20:17:49 +02004835 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4836 goto out;
4837
Willy Tarreau13943ab2006-12-31 00:24:10 +01004838 if (curproxy->cap & PR_CAP_FE)
4839 curproxy->options |= PR_O_TCP_CLI_KA;
4840 if (curproxy->cap & PR_CAP_BE)
4841 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
4843 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004844 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004845 err_code |= ERR_WARN;
4846
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004848 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004849 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004850 curproxy->options2 &= ~PR_O2_CHK_ANY;
4851 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 if (!*args[2]) { /* no argument */
4853 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4854 curproxy->check_len = strlen(DEF_CHECK_REQ);
4855 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004856 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004857 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004859 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004861 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 if (*args[4])
4863 reqlen += strlen(args[4]);
4864 else
4865 reqlen += strlen("HTTP/1.0");
4866
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004867 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004869 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004871 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4872 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004873 }
4874 else if (!strcmp(args[1], "ssl-hello-chk")) {
4875 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004877 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004878
Willy Tarreaua534fea2008-08-03 12:19:50 +02004879 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004880 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004881 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004882 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004883
4884 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 }
Willy Tarreau23677902007-05-08 23:50:35 +02004887 else if (!strcmp(args[1], "smtpchk")) {
4888 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004889 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004890 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004891 curproxy->options2 &= ~PR_O2_CHK_ANY;
4892 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004893
4894 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4895 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4896 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4897 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4898 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4899 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004900 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004901 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4902 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4903 } else {
4904 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4905 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4906 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4907 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4908 }
4909 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004910 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4911 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004912 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004913 else if (!strcmp(args[1], "pgsql-check")) {
4914 /* use PostgreSQL request to check servers' health */
4915 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4916 err_code |= ERR_WARN;
4917
4918 free(curproxy->check_req);
4919 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004920 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004921 curproxy->options2 |= PR_O2_PGSQL_CHK;
4922
4923 if (*(args[2])) {
4924 int cur_arg = 2;
4925
4926 while (*(args[cur_arg])) {
4927 if (strcmp(args[cur_arg], "user") == 0) {
4928 char * packet;
4929 uint32_t packet_len;
4930 uint32_t pv;
4931
4932 /* suboption header - needs additional argument for it */
4933 if (*(args[cur_arg+1]) == 0) {
4934 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4935 file, linenum, args[0], args[1], args[cur_arg]);
4936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
4938 }
4939
4940 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4941 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4942 pv = htonl(0x30000); /* protocol version 3.0 */
4943
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004944 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004945
4946 memcpy(packet + 4, &pv, 4);
4947
4948 /* copy "user" */
4949 memcpy(packet + 8, "user", 4);
4950
4951 /* copy username */
4952 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4953
4954 free(curproxy->check_req);
4955 curproxy->check_req = packet;
4956 curproxy->check_len = packet_len;
4957
4958 packet_len = htonl(packet_len);
4959 memcpy(packet, &packet_len, 4);
4960 cur_arg += 2;
4961 } else {
4962 /* unknown suboption - catchall */
4963 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4964 file, linenum, args[0], args[1]);
4965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
4967 }
4968 } /* end while loop */
4969 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004970 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4971 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004972 }
4973
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004974 else if (!strcmp(args[1], "redis-check")) {
4975 /* use REDIS PING request to check servers' health */
4976 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4977 err_code |= ERR_WARN;
4978
4979 free(curproxy->check_req);
4980 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004981 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004982 curproxy->options2 |= PR_O2_REDIS_CHK;
4983
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004984 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004985 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4986 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004987
4988 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4989 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004990 }
4991
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004992 else if (!strcmp(args[1], "mysql-check")) {
4993 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4995 err_code |= ERR_WARN;
4996
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004997 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004998 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004999 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005000 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005001
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005002 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005003 * const char mysql40_client_auth_pkt[] = {
5004 * "\x0e\x00\x00" // packet length
5005 * "\x01" // packet number
5006 * "\x00\x00" // client capabilities
5007 * "\x00\x00\x01" // max packet
5008 * "haproxy\x00" // username (null terminated string)
5009 * "\x00" // filler (always 0x00)
5010 * "\x01\x00\x00" // packet length
5011 * "\x00" // packet number
5012 * "\x01" // COM_QUIT command
5013 * };
5014 */
5015
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005016 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5017 * const char mysql41_client_auth_pkt[] = {
5018 * "\x0e\x00\x00\" // packet length
5019 * "\x01" // packet number
5020 * "\x00\x00\x00\x00" // client capabilities
5021 * "\x00\x00\x00\x01" // max packet
5022 * "\x21" // character set (UTF-8)
5023 * char[23] // All zeroes
5024 * "haproxy\x00" // username (null terminated string)
5025 * "\x00" // filler (always 0x00)
5026 * "\x01\x00\x00" // packet length
5027 * "\x00" // packet number
5028 * "\x01" // COM_QUIT command
5029 * };
5030 */
5031
5032
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005033 if (*(args[2])) {
5034 int cur_arg = 2;
5035
5036 while (*(args[cur_arg])) {
5037 if (strcmp(args[cur_arg], "user") == 0) {
5038 char *mysqluser;
5039 int packetlen, reqlen, userlen;
5040
5041 /* suboption header - needs additional argument for it */
5042 if (*(args[cur_arg+1]) == 0) {
5043 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5044 file, linenum, args[0], args[1], args[cur_arg]);
5045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
5047 }
5048 mysqluser = args[cur_arg + 1];
5049 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005050
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005051 if (*(args[cur_arg+2])) {
5052 if (!strcmp(args[cur_arg+2], "post-41")) {
5053 packetlen = userlen + 7 + 27;
5054 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005055
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005056 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005057 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005058 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005059
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005060 snprintf(curproxy->check_req, 4, "%c%c%c",
5061 ((unsigned char) packetlen & 0xff),
5062 ((unsigned char) (packetlen >> 8) & 0xff),
5063 ((unsigned char) (packetlen >> 16) & 0xff));
5064
5065 curproxy->check_req[3] = 1;
5066 curproxy->check_req[5] = 130;
5067 curproxy->check_req[11] = 1;
5068 curproxy->check_req[12] = 33;
5069 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5070 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5071 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5072 cur_arg += 3;
5073 } else {
5074 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5075 err_code |= ERR_ALERT | ERR_FATAL;
5076 goto out;
5077 }
5078 } else {
5079 packetlen = userlen + 7;
5080 reqlen = packetlen + 9;
5081
5082 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005083 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005084 curproxy->check_len = reqlen;
5085
5086 snprintf(curproxy->check_req, 4, "%c%c%c",
5087 ((unsigned char) packetlen & 0xff),
5088 ((unsigned char) (packetlen >> 8) & 0xff),
5089 ((unsigned char) (packetlen >> 16) & 0xff));
5090
5091 curproxy->check_req[3] = 1;
5092 curproxy->check_req[5] = 128;
5093 curproxy->check_req[8] = 1;
5094 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5095 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5096 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5097 cur_arg += 2;
5098 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005099 } else {
5100 /* unknown suboption - catchall */
5101 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5102 file, linenum, args[0], args[1]);
5103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
5105 }
5106 } /* end while loop */
5107 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005108 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005109 else if (!strcmp(args[1], "ldap-check")) {
5110 /* use LDAP request to check servers' health */
5111 free(curproxy->check_req);
5112 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005113 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005114 curproxy->options2 |= PR_O2_LDAP_CHK;
5115
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005116 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005117 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5118 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005119 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5120 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005121 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005122 else if (!strcmp(args[1], "spop-check")) {
5123 if (curproxy == &defproxy) {
5124 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5125 file, linenum, args[0], args[1]);
5126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
5129 if (curproxy->cap & PR_CAP_FE) {
5130 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5131 file, linenum, args[0], args[1]);
5132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
5135
5136 /* use SPOE request to check servers' health */
5137 free(curproxy->check_req);
5138 curproxy->check_req = NULL;
5139 curproxy->options2 &= ~PR_O2_CHK_ANY;
5140 curproxy->options2 |= PR_O2_SPOP_CHK;
5141
5142 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
5143 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
5146 }
5147 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5148 goto out;
5149 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005150 else if (!strcmp(args[1], "tcp-check")) {
5151 /* use raw TCPCHK send/expect to check servers' health */
5152 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5153 err_code |= ERR_WARN;
5154
5155 free(curproxy->check_req);
5156 curproxy->check_req = NULL;
5157 curproxy->options2 &= ~PR_O2_CHK_ANY;
5158 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005159 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5160 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005161 }
Simon Horman98637e52014-06-20 12:30:16 +09005162 else if (!strcmp(args[1], "external-check")) {
5163 /* excute an external command to check servers' health */
5164 free(curproxy->check_req);
5165 curproxy->check_req = NULL;
5166 curproxy->options2 &= ~PR_O2_CHK_ANY;
5167 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005168 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5169 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005170 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005171 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005172 int cur_arg;
5173
5174 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5175 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005176 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005177
Willy Tarreau87cf5142011-08-19 22:57:24 +02005178 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005179
5180 free(curproxy->fwdfor_hdr_name);
5181 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5182 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5183
5184 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5185 cur_arg = 2;
5186 while (*(args[cur_arg])) {
5187 if (!strcmp(args[cur_arg], "except")) {
5188 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005189 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005190 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5191 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005194 }
5195 /* flush useless bits */
5196 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005197 cur_arg += 2;
5198 } else if (!strcmp(args[cur_arg], "header")) {
5199 /* suboption header - needs additional argument for it */
5200 if (*(args[cur_arg+1]) == 0) {
5201 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5202 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005205 }
5206 free(curproxy->fwdfor_hdr_name);
5207 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5208 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5209 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005210 } else if (!strcmp(args[cur_arg], "if-none")) {
5211 curproxy->options &= ~PR_O_FF_ALWAYS;
5212 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005213 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005214 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005215 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005216 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005219 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005220 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005221 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005222 else if (!strcmp(args[1], "originalto")) {
5223 int cur_arg;
5224
5225 /* insert x-original-to field, but not for the IP address listed as an except.
5226 * set default options (ie: bitfield, header name, etc)
5227 */
5228
5229 curproxy->options |= PR_O_ORGTO;
5230
5231 free(curproxy->orgto_hdr_name);
5232 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5233 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5234
Willy Tarreau87cf5142011-08-19 22:57:24 +02005235 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005236 cur_arg = 2;
5237 while (*(args[cur_arg])) {
5238 if (!strcmp(args[cur_arg], "except")) {
5239 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005240 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 +02005241 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5242 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005245 }
5246 /* flush useless bits */
5247 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5248 cur_arg += 2;
5249 } else if (!strcmp(args[cur_arg], "header")) {
5250 /* suboption header - needs additional argument for it */
5251 if (*(args[cur_arg+1]) == 0) {
5252 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5253 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005254 err_code |= ERR_ALERT | ERR_FATAL;
5255 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005256 }
5257 free(curproxy->orgto_hdr_name);
5258 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5259 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5260 cur_arg += 2;
5261 } else {
5262 /* unknown suboption - catchall */
5263 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5264 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005267 }
5268 } /* end while loop */
5269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 else {
5271 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
Willy Tarreau93893792009-07-23 13:19:11 +02005275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005277 else if (!strcmp(args[0], "default_backend")) {
5278 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005280
5281 if (*(args[1]) == 0) {
5282 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005285 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005286 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005287 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005288
5289 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5290 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005293 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005295
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005296 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5297 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 +01005298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 /* enable reconnections to dispatch */
5301 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005302
5303 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005306 else if (!strcmp(args[0], "http-reuse")) {
5307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5308 err_code |= ERR_WARN;
5309
5310 if (strcmp(args[1], "never") == 0) {
5311 /* enable a graceful server shutdown on an HTTP 404 response */
5312 curproxy->options &= ~PR_O_REUSE_MASK;
5313 curproxy->options |= PR_O_REUSE_NEVR;
5314 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5315 goto out;
5316 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005317 else if (strcmp(args[1], "safe") == 0) {
5318 /* enable a graceful server shutdown on an HTTP 404 response */
5319 curproxy->options &= ~PR_O_REUSE_MASK;
5320 curproxy->options |= PR_O_REUSE_SAFE;
5321 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5322 goto out;
5323 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005324 else if (strcmp(args[1], "aggressive") == 0) {
5325 curproxy->options &= ~PR_O_REUSE_MASK;
5326 curproxy->options |= PR_O_REUSE_AGGR;
5327 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5328 goto out;
5329 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005330 else if (strcmp(args[1], "always") == 0) {
5331 /* enable a graceful server shutdown on an HTTP 404 response */
5332 curproxy->options &= ~PR_O_REUSE_MASK;
5333 curproxy->options |= PR_O_REUSE_ALWS;
5334 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5335 goto out;
5336 }
5337 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005338 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
5341 }
5342 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005343 else if (!strcmp(args[0], "http-check")) {
5344 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005346
5347 if (strcmp(args[1], "disable-on-404") == 0) {
5348 /* enable a graceful server shutdown on an HTTP 404 response */
5349 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005350 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5351 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005352 }
Willy Tarreauef781042010-01-27 11:53:01 +01005353 else if (strcmp(args[1], "send-state") == 0) {
5354 /* enable emission of the apparent state of a server in HTTP checks */
5355 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005356 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5357 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005358 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005359 else if (strcmp(args[1], "expect") == 0) {
5360 const char *ptr_arg;
5361 int cur_arg;
5362
5363 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5364 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368
5369 cur_arg = 2;
5370 /* consider exclamation marks, sole or at the beginning of a word */
5371 while (*(ptr_arg = args[cur_arg])) {
5372 while (*ptr_arg == '!') {
5373 curproxy->options2 ^= PR_O2_EXP_INV;
5374 ptr_arg++;
5375 }
5376 if (*ptr_arg)
5377 break;
5378 cur_arg++;
5379 }
5380 /* now ptr_arg points to the beginning of a word past any possible
5381 * exclamation mark, and cur_arg is the argument which holds this word.
5382 */
5383 if (strcmp(ptr_arg, "status") == 0) {
5384 if (!*(args[cur_arg + 1])) {
5385 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5386 file, linenum, args[0], args[1], ptr_arg);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 }
5390 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005391 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005392 curproxy->expect_str = strdup(args[cur_arg + 1]);
5393 }
5394 else if (strcmp(ptr_arg, "string") == 0) {
5395 if (!*(args[cur_arg + 1])) {
5396 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5397 file, linenum, args[0], args[1], ptr_arg);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
5401 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005402 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005403 curproxy->expect_str = strdup(args[cur_arg + 1]);
5404 }
5405 else if (strcmp(ptr_arg, "rstatus") == 0) {
5406 if (!*(args[cur_arg + 1])) {
5407 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5408 file, linenum, args[0], args[1], ptr_arg);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005413 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005414 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005415 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005416 free(curproxy->expect_regex);
5417 curproxy->expect_regex = NULL;
5418 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005419 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005420 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5421 error = NULL;
5422 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5423 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5424 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5425 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
5429 }
5430 else if (strcmp(ptr_arg, "rstring") == 0) {
5431 if (!*(args[cur_arg + 1])) {
5432 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5433 file, linenum, args[0], args[1], ptr_arg);
5434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
5437 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005438 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005439 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005440 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005441 free(curproxy->expect_regex);
5442 curproxy->expect_regex = NULL;
5443 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005444 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005445 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5446 error = NULL;
5447 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5448 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5449 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5450 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
5454 }
5455 else {
5456 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5457 file, linenum, args[0], args[1], ptr_arg);
5458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
5460 }
5461 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005462 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005463 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 +02005464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005466 }
5467 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005468 else if (!strcmp(args[0], "tcp-check")) {
5469 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5470 err_code |= ERR_WARN;
5471
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005472 if (strcmp(args[1], "comment") == 0) {
5473 int cur_arg;
5474 struct tcpcheck_rule *tcpcheck;
5475
5476 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005477 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005478 tcpcheck->action = TCPCHK_ACT_COMMENT;
5479
5480 if (!*args[cur_arg + 1]) {
5481 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5482 file, linenum, args[cur_arg]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
5486
5487 tcpcheck->comment = strdup(args[cur_arg + 1]);
5488
5489 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005490 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5491 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005492 }
5493 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005494 const char *ptr_arg;
5495 int cur_arg;
5496 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005497
5498 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005499 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5500 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5501 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5502 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5503 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005504
Willy Tarreau5581c272015-05-13 12:24:53 +02005505 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5506 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5507 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5508 file, linenum);
5509 err_code |= ERR_ALERT | ERR_FATAL;
5510 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005511 }
5512
5513 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005514 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005515 tcpcheck->action = TCPCHK_ACT_CONNECT;
5516
5517 /* parsing each parameters to fill up the rule */
5518 while (*(ptr_arg = args[cur_arg])) {
5519 /* tcp port */
5520 if (strcmp(args[cur_arg], "port") == 0) {
5521 if ( (atol(args[cur_arg + 1]) > 65535) ||
5522 (atol(args[cur_arg + 1]) < 1) ){
5523 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5524 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528 tcpcheck->port = atol(args[cur_arg + 1]);
5529 cur_arg += 2;
5530 }
5531 /* send proxy protocol */
5532 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5533 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5534 cur_arg++;
5535 }
5536#ifdef USE_OPENSSL
5537 else if (strcmp(args[cur_arg], "ssl") == 0) {
5538 curproxy->options |= PR_O_TCPCHK_SSL;
5539 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5540 cur_arg++;
5541 }
5542#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005543 /* comment for this tcpcheck line */
5544 else if (strcmp(args[cur_arg], "comment") == 0) {
5545 if (!*args[cur_arg + 1]) {
5546 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5547 file, linenum, args[cur_arg]);
5548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
5550 }
5551 tcpcheck->comment = strdup(args[cur_arg + 1]);
5552 cur_arg += 2;
5553 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005554 else {
5555#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005556 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005557#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005558 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005559#endif /* USE_OPENSSL */
5560 file, linenum, args[0], args[1], args[cur_arg]);
5561 err_code |= ERR_ALERT | ERR_FATAL;
5562 goto out;
5563 }
5564
5565 }
5566
5567 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5568 }
5569 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005570 if (! *(args[2]) ) {
5571 /* SEND string expected */
5572 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5573 file, linenum, args[0], args[1], args[2]);
5574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 } else {
5577 struct tcpcheck_rule *tcpcheck;
5578
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005579 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580
5581 tcpcheck->action = TCPCHK_ACT_SEND;
5582 tcpcheck->string_len = strlen(args[2]);
5583 tcpcheck->string = strdup(args[2]);
5584 tcpcheck->expect_regex = NULL;
5585
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005586 /* comment for this tcpcheck line */
5587 if (strcmp(args[3], "comment") == 0) {
5588 if (!*args[4]) {
5589 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5590 file, linenum, args[3]);
5591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
5593 }
5594 tcpcheck->comment = strdup(args[4]);
5595 }
5596
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005597 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5598 }
5599 }
5600 else if (strcmp(args[1], "send-binary") == 0) {
5601 if (! *(args[2]) ) {
5602 /* SEND binary string expected */
5603 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5604 file, linenum, args[0], args[1], args[2]);
5605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 } else {
5608 struct tcpcheck_rule *tcpcheck;
5609 char *err = NULL;
5610
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005611 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005612
5613 tcpcheck->action = TCPCHK_ACT_SEND;
5614 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5615 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5616 file, linenum, args[0], args[1], args[2], err);
5617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
5619 }
5620 tcpcheck->expect_regex = NULL;
5621
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005622 /* comment for this tcpcheck line */
5623 if (strcmp(args[3], "comment") == 0) {
5624 if (!*args[4]) {
5625 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5626 file, linenum, args[3]);
5627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
5629 }
5630 tcpcheck->comment = strdup(args[4]);
5631 }
5632
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005633 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5634 }
5635 }
5636 else if (strcmp(args[1], "expect") == 0) {
5637 const char *ptr_arg;
5638 int cur_arg;
5639 int inverse = 0;
5640
5641 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5642 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
5645 }
5646
5647 cur_arg = 2;
5648 /* consider exclamation marks, sole or at the beginning of a word */
5649 while (*(ptr_arg = args[cur_arg])) {
5650 while (*ptr_arg == '!') {
5651 inverse = !inverse;
5652 ptr_arg++;
5653 }
5654 if (*ptr_arg)
5655 break;
5656 cur_arg++;
5657 }
5658 /* now ptr_arg points to the beginning of a word past any possible
5659 * exclamation mark, and cur_arg is the argument which holds this word.
5660 */
5661 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005662 struct tcpcheck_rule *tcpcheck;
5663 char *err = NULL;
5664
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005665 if (!*(args[cur_arg + 1])) {
5666 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5667 file, linenum, args[0], args[1], ptr_arg);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005671
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005672 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005673
5674 tcpcheck->action = TCPCHK_ACT_EXPECT;
5675 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5676 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5677 file, linenum, args[0], args[1], args[2], err);
5678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
5680 }
5681 tcpcheck->expect_regex = NULL;
5682 tcpcheck->inverse = inverse;
5683
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005684 /* tcpcheck comment */
5685 cur_arg += 2;
5686 if (strcmp(args[cur_arg], "comment") == 0) {
5687 if (!*args[cur_arg + 1]) {
5688 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5689 file, linenum, args[cur_arg + 1]);
5690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
5692 }
5693 tcpcheck->comment = strdup(args[cur_arg + 1]);
5694 }
5695
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005696 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5697 }
5698 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005699 struct tcpcheck_rule *tcpcheck;
5700
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005701 if (!*(args[cur_arg + 1])) {
5702 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5703 file, linenum, args[0], args[1], ptr_arg);
5704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
5706 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005707
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005708 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005709
5710 tcpcheck->action = TCPCHK_ACT_EXPECT;
5711 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5712 tcpcheck->string = strdup(args[cur_arg + 1]);
5713 tcpcheck->expect_regex = NULL;
5714 tcpcheck->inverse = inverse;
5715
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005716 /* tcpcheck comment */
5717 cur_arg += 2;
5718 if (strcmp(args[cur_arg], "comment") == 0) {
5719 if (!*args[cur_arg + 1]) {
5720 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5721 file, linenum, args[cur_arg + 1]);
5722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
5724 }
5725 tcpcheck->comment = strdup(args[cur_arg + 1]);
5726 }
5727
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005728 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5729 }
5730 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005731 struct tcpcheck_rule *tcpcheck;
5732
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005733 if (!*(args[cur_arg + 1])) {
5734 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5735 file, linenum, args[0], args[1], ptr_arg);
5736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
5738 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005739
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005740 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005741
5742 tcpcheck->action = TCPCHK_ACT_EXPECT;
5743 tcpcheck->string_len = 0;
5744 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005745 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5746 error = NULL;
5747 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5748 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5749 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5750 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
5753 }
5754 tcpcheck->inverse = inverse;
5755
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005756 /* tcpcheck comment */
5757 cur_arg += 2;
5758 if (strcmp(args[cur_arg], "comment") == 0) {
5759 if (!*args[cur_arg + 1]) {
5760 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5761 file, linenum, args[cur_arg + 1]);
5762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
5764 }
5765 tcpcheck->comment = strdup(args[cur_arg + 1]);
5766 }
5767
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005768 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5769 }
5770 else {
5771 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5772 file, linenum, args[0], args[1], ptr_arg);
5773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
5775 }
5776 }
5777 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005778 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005779 err_code |= ERR_ALERT | ERR_FATAL;
5780 goto out;
5781 }
5782 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005783 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005784 if (curproxy == &defproxy) {
5785 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005788 }
5789
Willy Tarreaub80c2302007-11-30 20:51:32 +01005790 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005791 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005792
5793 if (strcmp(args[1], "fail") == 0) {
5794 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005795 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005796 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5797 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005800 }
5801
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005802 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5803 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5804 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005805 err_code |= ERR_ALERT | ERR_FATAL;
5806 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005807 }
5808 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5809 }
5810 else {
5811 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005812 err_code |= ERR_ALERT | ERR_FATAL;
5813 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005814 }
5815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816#ifdef TPROXY
5817 else if (!strcmp(args[0], "transparent")) {
5818 /* enable transparent proxy connections */
5819 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005820 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 }
5823#endif
5824 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005825 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005826 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005827
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 if (*(args[1]) == 0) {
5829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
5833 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005834 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005837 else if (!strcmp(args[0], "backlog")) { /* backlog */
5838 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005840
5841 if (*(args[1]) == 0) {
5842 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005845 }
5846 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005847 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5848 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005849 }
Willy Tarreau86034312006-12-29 00:10:33 +01005850 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005851 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005852 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005853
Willy Tarreau86034312006-12-29 00:10:33 +01005854 if (*(args[1]) == 0) {
5855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005856 err_code |= ERR_ALERT | ERR_FATAL;
5857 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005858 }
5859 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005860 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5861 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5864 if (*(args[1]) == 0) {
5865 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005869 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5870 if (err) {
5871 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5872 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005875 }
5876 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005877 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879 }
5880 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005881 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005882 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005883 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005884
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 if (curproxy == &defproxy) {
5886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005887 err_code |= ERR_ALERT | ERR_FATAL;
5888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005890 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005891 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005892
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005893 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005894 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005895 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005896 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005897 goto out;
5898 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005899
5900 proto = protocol_by_family(sk->ss_family);
5901 if (!proto || !proto->connect) {
5902 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5903 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
5907
5908 if (port1 != port2) {
5909 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5910 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005911 err_code |= ERR_ALERT | ERR_FATAL;
5912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005914
5915 if (!port1) {
5916 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5917 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005918 err_code |= ERR_ALERT | ERR_FATAL;
5919 goto out;
5920 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005921
William Lallemanddf1425a2015-04-28 20:17:49 +02005922 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5923 goto out;
5924
Willy Tarreaud5191e72010-02-09 20:50:45 +01005925 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005926 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005927 }
5928 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005929 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005930 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005931
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005932 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5933 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005938 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005939 /**
5940 * The syntax for hash-type config element is
5941 * hash-type {map-based|consistent} [[<algo>] avalanche]
5942 *
5943 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5944 */
5945 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005946
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005947 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5948 err_code |= ERR_WARN;
5949
5950 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005951 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5952 }
5953 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005954 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5955 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005956 else if (strcmp(args[1], "avalanche") == 0) {
5957 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]);
5958 err_code |= ERR_ALERT | ERR_FATAL;
5959 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005960 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005961 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005962 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005963 err_code |= ERR_ALERT | ERR_FATAL;
5964 goto out;
5965 }
Bhaskar98634f02013-10-29 23:30:51 -04005966
5967 /* set the hash function to use */
5968 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005969 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005970 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005971
5972 /* if consistent with no argument, then avalanche modifier is also applied */
5973 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5974 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005975 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005976 /* set the hash function */
5977 if (!strcmp(args[2], "sdbm")) {
5978 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5979 }
5980 else if (!strcmp(args[2], "djb2")) {
5981 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005982 }
5983 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005984 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005985 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005986 else if (!strcmp(args[2], "crc32")) {
5987 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5988 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005989 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005990 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 -05005991 err_code |= ERR_ALERT | ERR_FATAL;
5992 goto out;
5993 }
5994
5995 /* set the hash modifier */
5996 if (!strcmp(args[3], "avalanche")) {
5997 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5998 }
5999 else if (*args[3]) {
6000 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
6001 err_code |= ERR_ALERT | ERR_FATAL;
6002 goto out;
6003 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01006004 }
William Lallemanda73203e2012-03-12 12:48:57 +01006005 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04006006 else if (strcmp(args[0], "hash-balance-factor") == 0) {
6007 if (*(args[1]) == 0) {
6008 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
6009 err_code |= ERR_ALERT | ERR_FATAL;
6010 goto out;
6011 }
6012 curproxy->lbprm.chash.balance_factor = atol(args[1]);
6013 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
6014 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
6015 err_code |= ERR_ALERT | ERR_FATAL;
6016 goto out;
6017 }
6018 }
William Lallemanda73203e2012-03-12 12:48:57 +01006019 else if (strcmp(args[0], "unique-id-format") == 0) {
6020 if (!*(args[1])) {
6021 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6022 err_code |= ERR_ALERT | ERR_FATAL;
6023 goto out;
6024 }
William Lallemand3203ff42012-11-11 17:30:56 +01006025 if (*(args[2])) {
6026 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
6029 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006030 free(curproxy->conf.uniqueid_format_string);
6031 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006032
Willy Tarreau62a61232013-04-12 18:13:46 +02006033 free(curproxy->conf.uif_file);
6034 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6035 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006036 }
William Lallemanda73203e2012-03-12 12:48:57 +01006037
6038 else if (strcmp(args[0], "unique-id-header") == 0) {
6039 if (!*(args[1])) {
6040 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6041 err_code |= ERR_ALERT | ERR_FATAL;
6042 goto out;
6043 }
6044 free(curproxy->header_unique_id);
6045 curproxy->header_unique_id = strdup(args[1]);
6046 }
6047
William Lallemand723b73a2012-02-08 16:37:49 +01006048 else if (strcmp(args[0], "log-format") == 0) {
6049 if (!*(args[1])) {
6050 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6051 err_code |= ERR_ALERT | ERR_FATAL;
6052 goto out;
6053 }
William Lallemand3203ff42012-11-11 17:30:56 +01006054 if (*(args[2])) {
6055 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6056 err_code |= ERR_ALERT | ERR_FATAL;
6057 goto out;
6058 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006059
Willy Tarreau62a61232013-04-12 18:13:46 +02006060 if (curproxy->conf.logformat_string != default_http_log_format &&
6061 curproxy->conf.logformat_string != default_tcp_log_format &&
6062 curproxy->conf.logformat_string != clf_http_log_format)
6063 free(curproxy->conf.logformat_string);
6064 curproxy->conf.logformat_string = strdup(args[1]);
6065
6066 free(curproxy->conf.lfs_file);
6067 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6068 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006069
6070 /* get a chance to improve log-format error reporting by
6071 * reporting the correct line-number when possible.
6072 */
6073 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6074 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6075 file, linenum, curproxy->id);
6076 err_code |= ERR_WARN;
6077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006079 else if (!strcmp(args[0], "log-format-sd")) {
6080 if (!*(args[1])) {
6081 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
6084 }
6085 if (*(args[2])) {
6086 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6087 err_code |= ERR_ALERT | ERR_FATAL;
6088 goto out;
6089 }
6090
6091 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6092 free(curproxy->conf.logformat_sd_string);
6093 curproxy->conf.logformat_sd_string = strdup(args[1]);
6094
6095 free(curproxy->conf.lfsd_file);
6096 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6097 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6098
6099 /* get a chance to improve log-format-sd error reporting by
6100 * reporting the correct line-number when possible.
6101 */
6102 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6103 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6104 file, linenum, curproxy->id);
6105 err_code |= ERR_WARN;
6106 }
6107 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006108 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6109 if (*(args[1]) == 0) {
6110 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6111 err_code |= ERR_ALERT | ERR_FATAL;
6112 goto out;
6113 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006114 chunk_destroy(&curproxy->log_tag);
6115 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006116 }
William Lallemand0f99e342011-10-12 17:50:54 +02006117 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6118 /* delete previous herited or defined syslog servers */
6119 struct logsrv *back;
6120
6121 if (*(args[1]) != 0) {
6122 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6123 err_code |= ERR_ALERT | ERR_FATAL;
6124 goto out;
6125 }
6126
William Lallemand723b73a2012-02-08 16:37:49 +01006127 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6128 LIST_DEL(&tmplogsrv->list);
6129 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006130 }
6131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006132 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006133 struct logsrv *logsrv;
6134
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006136 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006137 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006138 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006139 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006140 LIST_INIT(&node->list);
6141 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006143 }
6144 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006145 struct sockaddr_storage *sk;
6146 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006147 int arg = 0;
6148 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006149
Vincent Bernat02779b62016-04-03 13:48:43 +02006150 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006151
Willy Tarreau18324f52014-06-27 18:10:07 +02006152 /* just after the address, a length may be specified */
6153 if (strcmp(args[arg+2], "len") == 0) {
6154 len = atoi(args[arg+3]);
6155 if (len < 80 || len > 65535) {
6156 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6157 file, linenum, args[arg+3]);
6158 err_code |= ERR_ALERT | ERR_FATAL;
6159 goto out;
6160 }
6161 logsrv->maxlen = len;
6162
6163 /* skip these two args */
6164 arg += 2;
6165 }
6166 else
6167 logsrv->maxlen = MAX_SYSLOG_LEN;
6168
6169 if (logsrv->maxlen > global.max_syslog_len) {
6170 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006171 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6172 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6173 logline = my_realloc2(logline, global.max_syslog_len + 1);
6174 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006175 }
6176
Dragan Dosen1322d092015-09-22 16:05:32 +02006177 /* after the length, a format may be specified */
6178 if (strcmp(args[arg+2], "format") == 0) {
6179 logsrv->format = get_log_format(args[arg+3]);
6180 if (logsrv->format < 0) {
6181 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
6184 }
6185
6186 /* skip these two args */
6187 arg += 2;
6188 }
6189
William Lallemanddf1425a2015-04-28 20:17:49 +02006190 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6191 goto out;
6192
Willy Tarreau18324f52014-06-27 18:10:07 +02006193 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006194 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006195 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006196 err_code |= ERR_ALERT | ERR_FATAL;
6197 goto out;
6198
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 }
6200
William Lallemand0f99e342011-10-12 17:50:54 +02006201 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006202 if (*(args[arg+3])) {
6203 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006204 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006205 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006206 err_code |= ERR_ALERT | ERR_FATAL;
6207 goto out;
6208
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 }
6210 }
6211
William Lallemand0f99e342011-10-12 17:50:54 +02006212 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006213 if (*(args[arg+4])) {
6214 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006215 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006216 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006217 err_code |= ERR_ALERT | ERR_FATAL;
6218 goto out;
6219
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006220 }
6221 }
6222
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006223 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006224 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006225 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006226 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006227 goto out;
6228 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006229
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006230 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006231
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006232 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006233 if (port1 != port2) {
6234 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6235 file, linenum, args[0], args[1]);
6236 err_code |= ERR_ALERT | ERR_FATAL;
6237 goto out;
6238 }
6239
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006240 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006241 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006242 }
William Lallemand0f99e342011-10-12 17:50:54 +02006243
6244 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 }
6246 else {
6247 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6248 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006249 err_code |= ERR_ALERT | ERR_FATAL;
6250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251 }
6252 }
6253 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006254 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006255 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006256 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006257 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006258
Willy Tarreau977b8e42006-12-29 14:19:17 +01006259 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006260 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006261
Willy Tarreaubaaee002006-06-26 02:48:02 +02006262 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006263 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6264 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006268
6269 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006270 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6271 free(curproxy->conn_src.iface_name);
6272 curproxy->conn_src.iface_name = NULL;
6273 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006274
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006275 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006276 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006277 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006278 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006279 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006280 goto out;
6281 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006282
6283 proto = protocol_by_family(sk->ss_family);
6284 if (!proto || !proto->connect) {
6285 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006286 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006287 err_code |= ERR_ALERT | ERR_FATAL;
6288 goto out;
6289 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006290
6291 if (port1 != port2) {
6292 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6293 file, linenum, args[0], args[1]);
6294 err_code |= ERR_ALERT | ERR_FATAL;
6295 goto out;
6296 }
6297
Willy Tarreauef9a3602012-12-08 22:29:20 +01006298 curproxy->conn_src.source_addr = *sk;
6299 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006300
6301 cur_arg = 2;
6302 while (*(args[cur_arg])) {
6303 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006304#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006305 if (!*args[cur_arg + 1]) {
6306 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6307 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006310 }
6311
6312 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006313 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6314 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006315 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006316 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6317 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006318 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6319 char *name, *end;
6320
6321 name = args[cur_arg+1] + 7;
6322 while (isspace(*name))
6323 name++;
6324
6325 end = name;
6326 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6327 end++;
6328
Willy Tarreauef9a3602012-12-08 22:29:20 +01006329 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6330 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6331 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6332 curproxy->conn_src.bind_hdr_len = end - name;
6333 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6334 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6335 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006336
6337 /* now look for an occurrence number */
6338 while (isspace(*end))
6339 end++;
6340 if (*end == ',') {
6341 end++;
6342 name = end;
6343 if (*end == '-')
6344 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006345 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006346 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006347 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006348 }
6349
Willy Tarreauef9a3602012-12-08 22:29:20 +01006350 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006351 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6352 " occurrences values smaller than %d.\n",
6353 file, linenum, MAX_HDR_HISTORY);
6354 err_code |= ERR_ALERT | ERR_FATAL;
6355 goto out;
6356 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006357 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006358 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006359
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006360 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006361 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006362 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006363 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006364 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006365 goto out;
6366 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006367
6368 proto = protocol_by_family(sk->ss_family);
6369 if (!proto || !proto->connect) {
6370 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6371 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006372 err_code |= ERR_ALERT | ERR_FATAL;
6373 goto out;
6374 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006375
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006376 if (port1 != port2) {
6377 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6378 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006379 err_code |= ERR_ALERT | ERR_FATAL;
6380 goto out;
6381 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006382 curproxy->conn_src.tproxy_addr = *sk;
6383 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006384 }
6385 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006386#else /* no TPROXY support */
6387 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006388 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006389 err_code |= ERR_ALERT | ERR_FATAL;
6390 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006391#endif
6392 cur_arg += 2;
6393 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006394 }
6395
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006396 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6397#ifdef SO_BINDTODEVICE
6398 if (!*args[cur_arg + 1]) {
6399 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6400 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006401 err_code |= ERR_ALERT | ERR_FATAL;
6402 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006403 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006404 free(curproxy->conn_src.iface_name);
6405 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6406 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006407 global.last_checks |= LSTCHK_NETADM;
6408#else
6409 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6410 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006411 err_code |= ERR_ALERT | ERR_FATAL;
6412 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006413#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006414 cur_arg += 2;
6415 continue;
6416 }
6417 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006418 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006419 err_code |= ERR_ALERT | ERR_FATAL;
6420 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006423 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6424 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6425 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006426 err_code |= ERR_ALERT | ERR_FATAL;
6427 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6432 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006433 err_code |= ERR_ALERT | ERR_FATAL;
6434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436
6437 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006438 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006439 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006440 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 }
6443 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006444 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006445 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006446 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006447 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 }
6450 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006451 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006452 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006453 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006454 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
6457 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006459 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006460 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006461 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006463 }
6464 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006466 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006467 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006468 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006471 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006472 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006473 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006474 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006476 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6481 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006482 err_code |= ERR_ALERT | ERR_FATAL;
6483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485
6486 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006487 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006488 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 }
6492 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006494 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006495 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 }
6499 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006501 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006502 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 }
6506 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006508 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006509 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 }
6513 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006514 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006515 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006516 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006517 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006520 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006521 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006522 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006523 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006524 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006525 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006528 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006529
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 if (curproxy == &defproxy) {
6531 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006532 err_code |= ERR_ALERT | ERR_FATAL;
6533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006535 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006536 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 if (*(args[1]) == 0) {
6539 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006540 err_code |= ERR_ALERT | ERR_FATAL;
6541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006543
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006544 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006545 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6546 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6547 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006548 err_code |= ERR_ALERT | ERR_FATAL;
6549 goto out;
6550 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006551 err_code |= warnif_cond_conflicts(cond,
6552 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6553 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006554 }
6555 else if (*args[2]) {
6556 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6557 file, linenum, args[0], args[2]);
6558 err_code |= ERR_ALERT | ERR_FATAL;
6559 goto out;
6560 }
6561
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006562 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006563 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006564 wl->s = strdup(args[1]);
6565 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006566 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006567 }
6568 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006569 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006572 err_code |= ERR_ALERT | ERR_FATAL;
6573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006574 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006575
Willy Tarreauade5ec42010-01-28 19:33:49 +01006576 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006577 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006578 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006579 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 }
6582 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006583 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006584 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006585 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006586 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
6589 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006590 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006591 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006592 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006593 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595 }
6596 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006597 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006598 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6599 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006600 err_code |= ERR_ALERT | ERR_FATAL;
6601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 }
6603
Willy Tarreauade5ec42010-01-28 19:33:49 +01006604 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006605 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006606 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006607 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
6610 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006611 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006612 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006613 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006614 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 }
6617 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006618 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006619 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006620 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006621 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006623 }
6624 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006625 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006626
Willy Tarreaubaaee002006-06-26 02:48:02 +02006627 if (curproxy == &defproxy) {
6628 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006629 err_code |= ERR_ALERT | ERR_FATAL;
6630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006631 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006632 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006633 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006634
Willy Tarreaubaaee002006-06-26 02:48:02 +02006635 if (*(args[1]) == 0) {
6636 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006637 err_code |= ERR_ALERT | ERR_FATAL;
6638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006639 }
6640
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006641 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006642 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6643 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6644 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006645 err_code |= ERR_ALERT | ERR_FATAL;
6646 goto out;
6647 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006648 err_code |= warnif_cond_conflicts(cond,
6649 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6650 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006651 }
6652 else if (*args[2]) {
6653 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6654 file, linenum, args[0], args[2]);
6655 err_code |= ERR_ALERT | ERR_FATAL;
6656 goto out;
6657 }
6658
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006659 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006660 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006661 wl->s = strdup(args[1]);
6662 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006663 }
6664 else if (!strcmp(args[0], "errorloc") ||
6665 !strcmp(args[0], "errorloc302") ||
6666 !strcmp(args[0], "errorloc303")) { /* error location */
6667 int errnum, errlen;
6668 char *err;
6669
Willy Tarreau977b8e42006-12-29 14:19:17 +01006670 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006671 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006672
Willy Tarreaubaaee002006-06-26 02:48:02 +02006673 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006674 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006675 err_code |= ERR_ALERT | ERR_FATAL;
6676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006677 }
6678
6679 errnum = atol(args[1]);
6680 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006681 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6682 err = malloc(errlen);
6683 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006684 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006685 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6686 err = malloc(errlen);
6687 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006688 }
6689
Willy Tarreau0f772532006-12-23 20:51:41 +01006690 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6691 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006692 chunk_destroy(&curproxy->errmsg[rc]);
6693 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006694 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006696 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006697
6698 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006699 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6700 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006701 free(err);
6702 }
6703 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006704 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6705 int errnum, errlen, fd;
6706 char *err;
6707 struct stat stat;
6708
6709 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006710 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006711
6712 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006713 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006714 err_code |= ERR_ALERT | ERR_FATAL;
6715 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006716 }
6717
6718 fd = open(args[2], O_RDONLY);
6719 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6720 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6721 file, linenum, args[2], args[1]);
6722 if (fd >= 0)
6723 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006724 err_code |= ERR_ALERT | ERR_FATAL;
6725 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006726 }
6727
Willy Tarreau27a674e2009-08-17 07:23:33 +02006728 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006729 errlen = stat.st_size;
6730 } else {
6731 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006732 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006733 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006734 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006735 }
6736
6737 err = malloc(errlen); /* malloc() must succeed during parsing */
6738 errnum = read(fd, err, errlen);
6739 if (errnum != errlen) {
6740 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6741 file, linenum, args[2], args[1]);
6742 close(fd);
6743 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006744 err_code |= ERR_ALERT | ERR_FATAL;
6745 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006746 }
6747 close(fd);
6748
6749 errnum = atol(args[1]);
6750 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6751 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006752 chunk_destroy(&curproxy->errmsg[rc]);
6753 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006754 break;
6755 }
6756 }
6757
6758 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006759 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6760 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006761 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006762 free(err);
6763 }
6764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006765 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006766 struct cfg_kw_list *kwl;
6767 int index;
6768
6769 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6770 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6771 if (kwl->kw[index].section != CFG_LISTEN)
6772 continue;
6773 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6774 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006775 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006776 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006777 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006778 err_code |= ERR_ALERT | ERR_FATAL;
6779 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006780 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006781 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006782 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006783 err_code |= ERR_WARN;
6784 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006785 }
Willy Tarreau93893792009-07-23 13:19:11 +02006786 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006787 }
6788 }
6789 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006790
Willy Tarreau6daf3432008-01-22 16:44:08 +01006791 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006792 err_code |= ERR_ALERT | ERR_FATAL;
6793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006794 }
Willy Tarreau93893792009-07-23 13:19:11 +02006795 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006796 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006797 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006798}
6799
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006801cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6802{
6803#ifdef CONFIG_HAP_NS
6804 const char *err;
6805 const char *item = args[0];
6806
6807 if (!strcmp(item, "namespace_list")) {
6808 return 0;
6809 }
6810 else if (!strcmp(item, "namespace")) {
6811 size_t idx = 1;
6812 const char *current;
6813 while (*(current = args[idx++])) {
6814 err = invalid_char(current);
6815 if (err) {
6816 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6817 file, linenum, *err, item, current);
6818 return ERR_ALERT | ERR_FATAL;
6819 }
6820
6821 if (netns_store_lookup(current, strlen(current))) {
6822 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6823 file, linenum, current);
6824 return ERR_ALERT | ERR_FATAL;
6825 }
6826 if (!netns_store_insert(current)) {
6827 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6828 file, linenum, current);
6829 return ERR_ALERT | ERR_FATAL;
6830 }
6831 }
6832 }
6833
6834 return 0;
6835#else
6836 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6837 file, linenum);
6838 return ERR_ALERT | ERR_FATAL;
6839#endif
6840}
6841
6842int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006843cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6844{
6845
6846 int err_code = 0;
6847 const char *err;
6848
6849 if (!strcmp(args[0], "userlist")) { /* new userlist */
6850 struct userlist *newul;
6851
6852 if (!*args[1]) {
6853 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6854 file, linenum, args[0]);
6855 err_code |= ERR_ALERT | ERR_FATAL;
6856 goto out;
6857 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6859 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006860
6861 err = invalid_char(args[1]);
6862 if (err) {
6863 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6864 file, linenum, *err, args[0], args[1]);
6865 err_code |= ERR_ALERT | ERR_FATAL;
6866 goto out;
6867 }
6868
6869 for (newul = userlist; newul; newul = newul->next)
6870 if (!strcmp(newul->name, args[1])) {
6871 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6872 file, linenum, args[1]);
6873 err_code |= ERR_WARN;
6874 goto out;
6875 }
6876
Vincent Bernat02779b62016-04-03 13:48:43 +02006877 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006878 if (!newul) {
6879 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6880 err_code |= ERR_ALERT | ERR_ABORT;
6881 goto out;
6882 }
6883
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006884 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006885 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006886 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6887 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006888 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006889 goto out;
6890 }
6891
6892 newul->next = userlist;
6893 userlist = newul;
6894
6895 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006896 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006897 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006898 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006899
6900 if (!*args[1]) {
6901 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6902 file, linenum, args[0]);
6903 err_code |= ERR_ALERT | ERR_FATAL;
6904 goto out;
6905 }
6906
6907 err = invalid_char(args[1]);
6908 if (err) {
6909 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6910 file, linenum, *err, args[0], args[1]);
6911 err_code |= ERR_ALERT | ERR_FATAL;
6912 goto out;
6913 }
6914
William Lallemand4ac9f542015-05-28 18:03:51 +02006915 if (!userlist)
6916 goto out;
6917
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006918 for (ag = userlist->groups; ag; ag = ag->next)
6919 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006920 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6921 file, linenum, args[1], userlist->name);
6922 err_code |= ERR_ALERT;
6923 goto out;
6924 }
6925
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006926 ag = calloc(1, sizeof(*ag));
6927 if (!ag) {
6928 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6929 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006930 goto out;
6931 }
6932
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006933 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006934 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006935 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6936 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006937 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006938 goto out;
6939 }
6940
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006941 cur_arg = 2;
6942
6943 while (*args[cur_arg]) {
6944 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006945 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006946 cur_arg += 2;
6947 continue;
6948 } else {
6949 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6950 file, linenum, args[0]);
6951 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006952 free(ag->groupusers);
6953 free(ag->name);
6954 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006955 goto out;
6956 }
6957 }
6958
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006959 ag->next = userlist->groups;
6960 userlist->groups = ag;
6961
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006962 } else if (!strcmp(args[0], "user")) { /* new user */
6963 struct auth_users *newuser;
6964 int cur_arg;
6965
6966 if (!*args[1]) {
6967 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6968 file, linenum, args[0]);
6969 err_code |= ERR_ALERT | ERR_FATAL;
6970 goto out;
6971 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006972 if (!userlist)
6973 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006974
6975 for (newuser = userlist->users; newuser; newuser = newuser->next)
6976 if (!strcmp(newuser->user, args[1])) {
6977 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6978 file, linenum, args[1], userlist->name);
6979 err_code |= ERR_ALERT;
6980 goto out;
6981 }
6982
Vincent Bernat02779b62016-04-03 13:48:43 +02006983 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006984 if (!newuser) {
6985 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6986 err_code |= ERR_ALERT | ERR_ABORT;
6987 goto out;
6988 }
6989
6990 newuser->user = strdup(args[1]);
6991
6992 newuser->next = userlist->users;
6993 userlist->users = newuser;
6994
6995 cur_arg = 2;
6996
6997 while (*args[cur_arg]) {
6998 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006999#ifdef CONFIG_HAP_CRYPT
7000 if (!crypt("", args[cur_arg + 1])) {
7001 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
7002 file, linenum, newuser->user);
7003 err_code |= ERR_ALERT | ERR_FATAL;
7004 goto out;
7005 }
7006#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007007 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
7008 file, linenum);
7009 err_code |= ERR_ALERT;
7010#endif
7011 newuser->pass = strdup(args[cur_arg + 1]);
7012 cur_arg += 2;
7013 continue;
7014 } else if (!strcmp(args[cur_arg], "insecure-password")) {
7015 newuser->pass = strdup(args[cur_arg + 1]);
7016 newuser->flags |= AU_O_INSECURE;
7017 cur_arg += 2;
7018 continue;
7019 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007020 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007021 cur_arg += 2;
7022 continue;
7023 } else {
7024 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7025 file, linenum, args[0]);
7026 err_code |= ERR_ALERT | ERR_FATAL;
7027 goto out;
7028 }
7029 }
7030 } else {
7031 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7032 err_code |= ERR_ALERT | ERR_FATAL;
7033 }
7034
7035out:
7036 return err_code;
7037}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007038
Christopher Faulet79bdef32016-11-04 22:36:15 +01007039int
7040cfg_parse_scope(const char *file, int linenum, char *line)
7041{
7042 char *beg, *end, *scope = NULL;
7043 int err_code = 0;
7044 const char *err;
7045
7046 beg = line + 1;
7047 end = strchr(beg, ']');
7048
7049 /* Detect end of scope declaration */
7050 if (!end || end == beg) {
7051 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7052 file, linenum);
7053 err_code |= ERR_ALERT | ERR_FATAL;
7054 goto out;
7055 }
7056
7057 /* Get scope name and check its validity */
7058 scope = my_strndup(beg, end-beg);
7059 err = invalid_char(scope);
7060 if (err) {
7061 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7062 file, linenum, *err);
7063 err_code |= ERR_ALERT | ERR_ABORT;
7064 goto out;
7065 }
7066
7067 /* Be sure to have a scope declaration alone on its line */
7068 line = end+1;
7069 while (isspace((unsigned char)*line))
7070 line++;
7071 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7072 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7073 file, linenum, *line);
7074 err_code |= ERR_ALERT | ERR_ABORT;
7075 goto out;
7076 }
7077
7078 /* We have a valid scope declaration, save it */
7079 free(cfg_scope);
7080 cfg_scope = scope;
7081 scope = NULL;
7082
7083 out:
7084 free(scope);
7085 return err_code;
7086}
7087
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088/*
7089 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007090 * Returns the error code, 0 if OK, or any combination of :
7091 * - ERR_ABORT: must abort ASAP
7092 * - ERR_FATAL: we can continue parsing but not start the service
7093 * - ERR_WARN: a warning has been emitted
7094 * - ERR_ALERT: an alert has been emitted
7095 * Only the two first ones can stop processing, the two others are just
7096 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007097 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007098int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007099{
William Lallemand64e84512015-05-12 14:25:37 +02007100 char *thisline;
7101 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102 FILE *f;
7103 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007104 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007105 struct cfg_section *cs = NULL;
7106 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007107 int readbytes = 0;
7108
7109 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007110 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007111 return -1;
7112 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007113
David Carlier97880bb2016-04-08 10:35:26 +01007114 if ((f=fopen(file,"r")) == NULL) {
7115 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007116 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007118
William Lallemandb2f07452015-05-12 14:27:13 +02007119next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007120 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007121 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007122 char *end;
7123 char *args[MAX_LINE_ARGS + 1];
7124 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007125 int dquote = 0; /* double quote */
7126 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007127
Willy Tarreaubaaee002006-06-26 02:48:02 +02007128 linenum++;
7129
7130 end = line + strlen(line);
7131
William Lallemand64e84512015-05-12 14:25:37 +02007132 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007133 /* Check if we reached the limit and the last char is not \n.
7134 * Watch out for the last line without the terminating '\n'!
7135 */
William Lallemand64e84512015-05-12 14:25:37 +02007136 char *newline;
7137 int newlinesize = linesize * 2;
7138
7139 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7140 if (newline == NULL) {
7141 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7142 file, linenum);
7143 err_code |= ERR_ALERT | ERR_FATAL;
7144 continue;
7145 }
7146
7147 readbytes = linesize - 1;
7148 linesize = newlinesize;
7149 thisline = newline;
7150 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007151 }
7152
William Lallemand64e84512015-05-12 14:25:37 +02007153 readbytes = 0;
7154
Willy Tarreaubaaee002006-06-26 02:48:02 +02007155 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007156 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007158
Christopher Faulet79bdef32016-11-04 22:36:15 +01007159
7160 if (*line == '[') {/* This is the begining if a scope */
7161 err_code |= cfg_parse_scope(file, linenum, line);
7162 goto next_line;
7163 }
7164
Willy Tarreaubaaee002006-06-26 02:48:02 +02007165 arg = 0;
7166 args[arg] = line;
7167
7168 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007169 if (*line == '"' && !squote) { /* double quote outside single quotes */
7170 if (dquote)
7171 dquote = 0;
7172 else
7173 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007174 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007175 end--;
7176 }
7177 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7178 if (squote)
7179 squote = 0;
7180 else
7181 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007182 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007183 end--;
7184 }
7185 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007186 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7187 * C equivalent value. Other combinations left unchanged (eg: \1).
7188 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007189 int skip = 0;
7190 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7191 *line = line[1];
7192 skip = 1;
7193 }
7194 else if (line[1] == 'r') {
7195 *line = '\r';
7196 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007198 else if (line[1] == 'n') {
7199 *line = '\n';
7200 skip = 1;
7201 }
7202 else if (line[1] == 't') {
7203 *line = '\t';
7204 skip = 1;
7205 }
7206 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007207 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007208 unsigned char hex1, hex2;
7209 hex1 = toupper(line[2]) - '0';
7210 hex2 = toupper(line[3]) - '0';
7211 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7212 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7213 *line = (hex1<<4) + hex2;
7214 skip = 3;
7215 }
7216 else {
7217 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007218 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007219 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007220 } else if (line[1] == '"') {
7221 *line = '"';
7222 skip = 1;
7223 } else if (line[1] == '\'') {
7224 *line = '\'';
7225 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007226 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7227 *line = '$';
7228 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007229 }
7230 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007231 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007232 end -= skip;
7233 }
7234 line++;
7235 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007236 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007237 /* end of string, end of loop */
7238 *line = 0;
7239 break;
7240 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007241 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007242 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007243 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007244 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007245 line++;
7246 args[++arg] = line;
7247 }
William Lallemandb2f07452015-05-12 14:27:13 +02007248 else if (dquote && *line == '$') {
7249 /* environment variables are evaluated inside double quotes */
7250 char *var_beg;
7251 char *var_end;
7252 char save_char;
7253 char *value;
7254 int val_len;
7255 int newlinesize;
7256 int braces = 0;
7257
7258 var_beg = line + 1;
7259 var_end = var_beg;
7260
7261 if (*var_beg == '{') {
7262 var_beg++;
7263 var_end++;
7264 braces = 1;
7265 }
7266
7267 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7268 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7269 err_code |= ERR_ALERT | ERR_FATAL;
7270 goto next_line; /* skip current line */
7271 }
7272
7273 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7274 var_end++;
7275
7276 save_char = *var_end;
7277 *var_end = '\0';
7278 value = getenv(var_beg);
7279 *var_end = save_char;
7280 val_len = value ? strlen(value) : 0;
7281
7282 if (braces) {
7283 if (*var_end == '}') {
7284 var_end++;
7285 braces = 0;
7286 } else {
7287 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7288 err_code |= ERR_ALERT | ERR_FATAL;
7289 goto next_line; /* skip current line */
7290 }
7291 }
7292
7293 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7294
7295 /* if not enough space in thisline */
7296 if (newlinesize > linesize) {
7297 char *newline;
7298
7299 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7300 if (newline == NULL) {
7301 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7302 err_code |= ERR_ALERT | ERR_FATAL;
7303 goto next_line; /* slip current line */
7304 }
7305 /* recompute pointers if realloc returns a new pointer */
7306 if (newline != thisline) {
7307 int i;
7308 int diff;
7309
7310 for (i = 0; i <= arg; i++) {
7311 diff = args[i] - thisline;
7312 args[i] = newline + diff;
7313 }
7314
7315 diff = var_end - thisline;
7316 var_end = newline + diff;
7317 diff = end - thisline;
7318 end = newline + diff;
7319 diff = line - thisline;
7320 line = newline + diff;
7321 thisline = newline;
7322 }
7323 linesize = newlinesize;
7324 }
7325
7326 /* insert value inside the line */
7327 memmove(line + val_len, var_end, end - var_end + 1);
7328 memcpy(line, value, val_len);
7329 end += val_len - (var_end - line);
7330 line += val_len;
7331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007332 else {
7333 line++;
7334 }
7335 }
William Lallemandb2f07452015-05-12 14:27:13 +02007336
William Lallemandf9873ba2015-05-05 17:37:14 +02007337 if (dquote) {
7338 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7339 err_code |= ERR_ALERT | ERR_FATAL;
7340 }
7341
7342 if (squote) {
7343 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7344 err_code |= ERR_ALERT | ERR_FATAL;
7345 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007346
7347 /* empty line */
7348 if (!**args)
7349 continue;
7350
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007351 if (*line) {
7352 /* we had to stop due to too many args.
7353 * Let's terminate the string, print the offending part then cut the
7354 * last arg.
7355 */
7356 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7357 line++;
7358 *line = '\0';
7359
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007360 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007361 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007362 err_code |= ERR_ALERT | ERR_FATAL;
7363 args[arg] = line;
7364 }
7365
Willy Tarreau540abe42007-05-02 20:50:16 +02007366 /* zero out remaining args and ensure that at least one entry
7367 * is zeroed out.
7368 */
7369 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007370 args[arg] = line;
7371 }
7372
Willy Tarreau3842f002009-06-14 11:39:52 +02007373 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007374 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007375 char *tmp;
7376
Willy Tarreau3842f002009-06-14 11:39:52 +02007377 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007378 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007379 for (arg=0; *args[arg+1]; arg++)
7380 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007381 *tmp = '\0'; // fix the next arg to \0
7382 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007383 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007384 else if (!strcmp(args[0], "default")) {
7385 kwm = KWM_DEF;
7386 for (arg=0; *args[arg+1]; arg++)
7387 args[arg] = args[arg+1]; // shift args after inversion
7388 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007389
William Lallemand0f99e342011-10-12 17:50:54 +02007390 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7391 strcmp(args[0], "log") != 0) {
7392 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007393 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007394 }
7395
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007396 /* detect section start */
7397 list_for_each_entry(ics, &sections, list) {
7398 if (strcmp(args[0], ics->section_name) == 0) {
7399 cursection = ics->section_name;
7400 cs = ics;
7401 break;
7402 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007403 }
7404
Willy Tarreaubaaee002006-06-26 02:48:02 +02007405 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007406 if (cs)
7407 err_code |= cs->section_parser(file, linenum, args, kwm);
7408 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007409 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007410 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007411 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007412
7413 if (err_code & ERR_ABORT)
7414 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007415 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007416 free(cfg_scope);
7417 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007418 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007419 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007420 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007421 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007422}
7423
Willy Tarreau64ab6072014-09-16 12:17:36 +02007424/* This function propagates processes from frontend <from> to backend <to> so
7425 * that it is always guaranteed that a backend pointed to by a frontend is
7426 * bound to all of its processes. After that, if the target is a "listen"
7427 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007428 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007429 * checked first to ensure that <to> is already bound to all processes of
7430 * <from>, there is no risk of looping and we ensure to follow the shortest
7431 * path to the destination.
7432 *
7433 * It is possible to set <to> to NULL for the first call so that the function
7434 * takes care of visiting the initial frontend in <from>.
7435 *
7436 * It is important to note that the function relies on the fact that all names
7437 * have already been resolved.
7438 */
7439void propagate_processes(struct proxy *from, struct proxy *to)
7440{
7441 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007442
7443 if (to) {
7444 /* check whether we need to go down */
7445 if (from->bind_proc &&
7446 (from->bind_proc & to->bind_proc) == from->bind_proc)
7447 return;
7448
7449 if (!from->bind_proc && !to->bind_proc)
7450 return;
7451
7452 to->bind_proc = from->bind_proc ?
7453 (to->bind_proc | from->bind_proc) : 0;
7454
7455 /* now propagate down */
7456 from = to;
7457 }
7458
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007459 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007460 return;
7461
Willy Tarreauf6b70012014-12-18 14:00:43 +01007462 if (from->state == PR_STSTOPPED)
7463 return;
7464
Willy Tarreau64ab6072014-09-16 12:17:36 +02007465 /* default_backend */
7466 if (from->defbe.be)
7467 propagate_processes(from, from->defbe.be);
7468
7469 /* use_backend */
7470 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007471 if (rule->dynamic)
7472 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007473 to = rule->be.backend;
7474 propagate_processes(from, to);
7475 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007476}
7477
Willy Tarreaubb925012009-07-23 13:36:36 +02007478/*
7479 * Returns the error code, 0 if OK, or any combination of :
7480 * - ERR_ABORT: must abort ASAP
7481 * - ERR_FATAL: we can continue parsing but not start the service
7482 * - ERR_WARN: a warning has been emitted
7483 * - ERR_ALERT: an alert has been emitted
7484 * Only the two first ones can stop processing, the two others are just
7485 * indicators.
7486 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007487int check_config_validity()
7488{
7489 int cfgerr = 0;
7490 struct proxy *curproxy = NULL;
7491 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007492 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007493 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007494 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007495
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007496 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007497 /*
7498 * Now, check for the integrity of all that we have collected.
7499 */
7500
7501 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007502 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007503
Willy Tarreau193b8c62012-11-22 00:17:38 +01007504 if (!global.tune.max_http_hdr)
7505 global.tune.max_http_hdr = MAX_HTTP_HDR;
7506
7507 if (!global.tune.cookie_len)
7508 global.tune.cookie_len = CAPTURE_LEN;
7509
7510 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7511
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007512 /* Post initialisation of the users and groups lists. */
7513 err_code = userlist_postinit();
7514 if (err_code != ERR_NONE)
7515 goto out;
7516
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007517 /* first, we will invert the proxy list order */
7518 curproxy = NULL;
7519 while (proxy) {
7520 struct proxy *next;
7521
7522 next = proxy->next;
7523 proxy->next = curproxy;
7524 curproxy = proxy;
7525 if (!next)
7526 break;
7527 proxy = next;
7528 }
7529
Willy Tarreau419ead82014-09-16 13:41:21 +02007530 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007531 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007532 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007533 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007534 struct act_rule *trule;
7535 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007536 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007537 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007538 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007539
Willy Tarreau050536d2012-10-04 08:47:34 +02007540 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007541 /* proxy ID not set, use automatic numbering with first
7542 * spare entry starting with next_pxid.
7543 */
7544 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7545 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7546 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007547 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007548 next_pxid++;
7549
Willy Tarreau55ea7572007-06-17 19:56:27 +02007550
Willy Tarreaubaaee002006-06-26 02:48:02 +02007551 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007552 /* ensure we don't keep listeners uselessly bound */
7553 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007554 free((void *)curproxy->table.peers.name);
7555 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007556 continue;
7557 }
7558
Willy Tarreau102df612014-05-07 23:56:38 +02007559 /* Check multi-process mode compatibility for the current proxy */
7560
7561 if (curproxy->bind_proc) {
7562 /* an explicit bind-process was specified, let's check how many
7563 * processes remain.
7564 */
David Carliere6c39412015-07-02 07:00:17 +00007565 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007566
7567 curproxy->bind_proc &= nbits(global.nbproc);
7568 if (!curproxy->bind_proc && nbproc == 1) {
7569 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);
7570 curproxy->bind_proc = 1;
7571 }
7572 else if (!curproxy->bind_proc && nbproc > 1) {
7573 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);
7574 curproxy->bind_proc = 0;
7575 }
7576 }
7577
Willy Tarreau3d209582014-05-09 17:06:11 +02007578 /* check and reduce the bind-proc of each listener */
7579 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7580 unsigned long mask;
7581
7582 if (!bind_conf->bind_proc)
7583 continue;
7584
7585 mask = nbits(global.nbproc);
7586 if (curproxy->bind_proc)
7587 mask &= curproxy->bind_proc;
7588 /* mask cannot be null here thanks to the previous checks */
7589
David Carliere6c39412015-07-02 07:00:17 +00007590 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007591 bind_conf->bind_proc &= mask;
7592
7593 if (!bind_conf->bind_proc && nbproc == 1) {
7594 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",
7595 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7596 bind_conf->bind_proc = mask & ~(mask - 1);
7597 }
7598 else if (!bind_conf->bind_proc && nbproc > 1) {
7599 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",
7600 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7601 bind_conf->bind_proc = 0;
7602 }
7603 }
7604
Willy Tarreauff01a212009-03-15 13:46:16 +01007605 switch (curproxy->mode) {
7606 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007607 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007608 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007609 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7610 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007611 cfgerr++;
7612 }
7613
7614 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007615 Warning("config : servers will be ignored for %s '%s'.\n",
7616 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007617 break;
7618
7619 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007620 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007621 break;
7622
7623 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007624 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007625 break;
7626 }
7627
Willy Tarreauf3934b82015-08-11 11:36:45 +02007628 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7629 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7630 proxy_type_str(curproxy), curproxy->id);
7631 err_code |= ERR_WARN;
7632 }
7633
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007634 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007635 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007636 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007637 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7638 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007639 cfgerr++;
7640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007641#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007642 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007643 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7644 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007645 cfgerr++;
7646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007647#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007648 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007649 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7650 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007651 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007652 }
7653 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007654 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007655 /* If no LB algo is set in a backend, and we're not in
7656 * transparent mode, dispatch mode nor proxy mode, we
7657 * want to use balance roundrobin by default.
7658 */
7659 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7660 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007661 }
7662 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007663
Willy Tarreau1620ec32011-08-06 17:05:02 +02007664 if (curproxy->options & PR_O_DISPATCH)
7665 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7666 else if (curproxy->options & PR_O_HTTP_PROXY)
7667 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7668 else if (curproxy->options & PR_O_TRANSP)
7669 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007670
Willy Tarreau1620ec32011-08-06 17:05:02 +02007671 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7672 if (curproxy->options & PR_O_DISABLE404) {
7673 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7674 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7675 err_code |= ERR_WARN;
7676 curproxy->options &= ~PR_O_DISABLE404;
7677 }
7678 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7679 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7680 "send-state", proxy_type_str(curproxy), curproxy->id);
7681 err_code |= ERR_WARN;
7682 curproxy->options &= ~PR_O2_CHK_SNDST;
7683 }
Willy Tarreauef781042010-01-27 11:53:01 +01007684 }
7685
Simon Horman98637e52014-06-20 12:30:16 +09007686 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7687 if (!global.external_check) {
7688 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7689 curproxy->id, "option external-check");
7690 cfgerr++;
7691 }
7692 if (!curproxy->check_command) {
7693 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7694 curproxy->id, "option external-check");
7695 cfgerr++;
7696 }
7697 }
7698
Simon Horman64e34162015-02-06 11:11:57 +09007699 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007700 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7701 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007702 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7703 "'email-alert myhostname', or 'email-alert to' "
7704 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007705 "to be present).\n",
7706 proxy_type_str(curproxy), curproxy->id);
7707 err_code |= ERR_WARN;
7708 free_email_alert(curproxy);
7709 }
7710 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007711 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007712 }
7713
Simon Horman98637e52014-06-20 12:30:16 +09007714 if (curproxy->check_command) {
7715 int clear = 0;
7716 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7717 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7718 "external-check command", proxy_type_str(curproxy), curproxy->id);
7719 err_code |= ERR_WARN;
7720 clear = 1;
7721 }
7722 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007723 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007724 curproxy->id, "external-check command");
7725 cfgerr++;
7726 }
7727 if (clear) {
7728 free(curproxy->check_command);
7729 curproxy->check_command = NULL;
7730 }
7731 }
7732
7733 if (curproxy->check_path) {
7734 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7735 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7736 "external-check path", proxy_type_str(curproxy), curproxy->id);
7737 err_code |= ERR_WARN;
7738 free(curproxy->check_path);
7739 curproxy->check_path = NULL;
7740 }
7741 }
7742
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007743 /* if a default backend was specified, let's find it */
7744 if (curproxy->defbe.name) {
7745 struct proxy *target;
7746
Willy Tarreauafb39922015-05-26 12:04:09 +02007747 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007748 if (!target) {
7749 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7750 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007751 cfgerr++;
7752 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007753 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7754 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007755 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007756 } else if (target->mode != curproxy->mode &&
7757 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7758
7759 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7760 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7761 curproxy->conf.file, curproxy->conf.line,
7762 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7763 target->conf.file, target->conf.line);
7764 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007765 } else {
7766 free(curproxy->defbe.name);
7767 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007768
7769 /* Emit a warning if this proxy also has some servers */
7770 if (curproxy->srv) {
7771 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7772 curproxy->id);
7773 err_code |= ERR_WARN;
7774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007775 }
7776 }
7777
Willy Tarreau55ea7572007-06-17 19:56:27 +02007778 /* find the target proxy for 'use_backend' rules */
7779 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007780 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007781 struct logformat_node *node;
7782 char *pxname;
7783
7784 /* Try to parse the string as a log format expression. If the result
7785 * of the parsing is only one entry containing a simple string, then
7786 * it's a standard string corresponding to a static rule, thus the
7787 * parsing is cancelled and be.name is restored to be resolved.
7788 */
7789 pxname = rule->be.name;
7790 LIST_INIT(&rule->be.expr);
7791 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7792 curproxy->conf.args.file, curproxy->conf.args.line);
7793 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7794
7795 if (!LIST_ISEMPTY(&rule->be.expr)) {
7796 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7797 rule->dynamic = 1;
7798 free(pxname);
7799 continue;
7800 }
7801 /* simple string: free the expression and fall back to static rule */
7802 free(node->arg);
7803 free(node);
7804 }
7805
7806 rule->dynamic = 0;
7807 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007808
Willy Tarreauafb39922015-05-26 12:04:09 +02007809 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007810 if (!target) {
7811 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7812 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007813 cfgerr++;
7814 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007815 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7816 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007817 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007818 } else if (target->mode != curproxy->mode &&
7819 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7820
7821 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7822 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7823 curproxy->conf.file, curproxy->conf.line,
7824 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7825 target->conf.file, target->conf.line);
7826 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007827 } else {
7828 free((void *)rule->be.name);
7829 rule->be.backend = target;
7830 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007831 }
7832
Willy Tarreau64ab6072014-09-16 12:17:36 +02007833 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007834 list_for_each_entry(srule, &curproxy->server_rules, list) {
7835 struct server *target = findserver(curproxy, srule->srv.name);
7836
7837 if (!target) {
7838 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7839 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7840 cfgerr++;
7841 continue;
7842 }
7843 free((void *)srule->srv.name);
7844 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007845 }
7846
Emeric Brunb982a3d2010-01-04 15:45:53 +01007847 /* find the target table for 'stick' rules */
7848 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7849 struct proxy *target;
7850
Emeric Brun1d33b292010-01-04 15:47:17 +01007851 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7852 if (mrule->flags & STK_IS_STORE)
7853 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7854
Emeric Brunb982a3d2010-01-04 15:45:53 +01007855 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007856 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007857 else
7858 target = curproxy;
7859
7860 if (!target) {
7861 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7862 curproxy->id, mrule->table.name);
7863 cfgerr++;
7864 }
7865 else if (target->table.size == 0) {
7866 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7867 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7868 cfgerr++;
7869 }
Willy Tarreau12785782012-04-27 21:37:17 +02007870 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7871 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007872 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7873 cfgerr++;
7874 }
7875 else {
7876 free((void *)mrule->table.name);
7877 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007878 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007879 }
7880 }
7881
7882 /* find the target table for 'store response' rules */
7883 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7884 struct proxy *target;
7885
Emeric Brun1d33b292010-01-04 15:47:17 +01007886 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7887
Emeric Brunb982a3d2010-01-04 15:45:53 +01007888 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007889 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007890 else
7891 target = curproxy;
7892
7893 if (!target) {
7894 Alert("Proxy '%s': unable to find store table '%s'.\n",
7895 curproxy->id, mrule->table.name);
7896 cfgerr++;
7897 }
7898 else if (target->table.size == 0) {
7899 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7900 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7901 cfgerr++;
7902 }
Willy Tarreau12785782012-04-27 21:37:17 +02007903 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7904 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007905 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7906 cfgerr++;
7907 }
7908 else {
7909 free((void *)mrule->table.name);
7910 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007911 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007912 }
7913 }
7914
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007915 /* find the target table for 'tcp-request' layer 4 rules */
7916 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7917 struct proxy *target;
7918
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007919 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007920 continue;
7921
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007922 if (trule->arg.trk_ctr.table.n)
7923 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007924 else
7925 target = curproxy;
7926
7927 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007928 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007929 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007930 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007931 cfgerr++;
7932 }
7933 else if (target->table.size == 0) {
7934 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007935 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007936 cfgerr++;
7937 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007938 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007939 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007940 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007941 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007942 cfgerr++;
7943 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007944 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007945 free(trule->arg.trk_ctr.table.n);
7946 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007947 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007948 * to pass a list of counters to track and allocate them right here using
7949 * stktable_alloc_data_type().
7950 */
7951 }
7952 }
7953
Willy Tarreau620408f2016-10-21 16:37:51 +02007954 /* find the target table for 'tcp-request' layer 5 rules */
7955 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7956 struct proxy *target;
7957
7958 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7959 continue;
7960
7961 if (trule->arg.trk_ctr.table.n)
7962 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7963 else
7964 target = curproxy;
7965
7966 if (!target) {
7967 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7968 curproxy->id, trule->arg.trk_ctr.table.n,
7969 tcp_trk_idx(trule->action));
7970 cfgerr++;
7971 }
7972 else if (target->table.size == 0) {
7973 Alert("Proxy '%s': table '%s' used but not configured.\n",
7974 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7975 cfgerr++;
7976 }
7977 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7978 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7979 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7980 tcp_trk_idx(trule->action));
7981 cfgerr++;
7982 }
7983 else {
7984 free(trule->arg.trk_ctr.table.n);
7985 trule->arg.trk_ctr.table.t = &target->table;
7986 /* Note: if we decide to enhance the track-sc syntax, we may be able
7987 * to pass a list of counters to track and allocate them right here using
7988 * stktable_alloc_data_type().
7989 */
7990 }
7991 }
7992
Willy Tarreaud1f96522010-08-03 19:34:32 +02007993 /* find the target table for 'tcp-request' layer 6 rules */
7994 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7995 struct proxy *target;
7996
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007997 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007998 continue;
7999
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008000 if (trule->arg.trk_ctr.table.n)
8001 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008002 else
8003 target = curproxy;
8004
8005 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02008006 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008007 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008008 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02008009 cfgerr++;
8010 }
8011 else if (target->table.size == 0) {
8012 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008013 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008014 cfgerr++;
8015 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008016 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01008017 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008018 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008019 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01008020 cfgerr++;
8021 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008022 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008023 free(trule->arg.trk_ctr.table.n);
8024 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02008025 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02008026 * to pass a list of counters to track and allocate them right here using
8027 * stktable_alloc_data_type().
8028 */
8029 }
8030 }
8031
Baptiste Assmanne9544932015-11-03 23:31:35 +01008032 /* parse http-request capture rules to ensure id really exists */
8033 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8034 if (hrqrule->action != ACT_CUSTOM ||
8035 hrqrule->action_ptr != http_action_req_capture_by_id)
8036 continue;
8037
8038 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8039 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8040 curproxy->id, hrqrule->arg.capid.idx);
8041 cfgerr++;
8042 }
8043 }
8044
8045 /* parse http-response capture rules to ensure id really exists */
8046 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8047 if (hrqrule->action != ACT_CUSTOM ||
8048 hrqrule->action_ptr != http_action_res_capture_by_id)
8049 continue;
8050
8051 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8052 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8053 curproxy->id, hrqrule->arg.capid.idx);
8054 cfgerr++;
8055 }
8056 }
8057
Willy Tarreau09448f72014-06-25 18:12:15 +02008058 /* find the target table for 'http-request' layer 7 rules */
8059 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8060 struct proxy *target;
8061
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008062 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008063 continue;
8064
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008065 if (hrqrule->arg.trk_ctr.table.n)
8066 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008067 else
8068 target = curproxy;
8069
8070 if (!target) {
8071 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008072 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008073 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008074 cfgerr++;
8075 }
8076 else if (target->table.size == 0) {
8077 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008078 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008079 cfgerr++;
8080 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008081 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008082 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008083 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008084 http_trk_idx(hrqrule->action));
8085 cfgerr++;
8086 }
8087 else {
8088 free(hrqrule->arg.trk_ctr.table.n);
8089 hrqrule->arg.trk_ctr.table.t = &target->table;
8090 /* Note: if we decide to enhance the track-sc syntax, we may be able
8091 * to pass a list of counters to track and allocate them right here using
8092 * stktable_alloc_data_type().
8093 */
8094 }
8095 }
8096
8097 /* find the target table for 'http-response' layer 7 rules */
8098 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8099 struct proxy *target;
8100
8101 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8102 continue;
8103
8104 if (hrqrule->arg.trk_ctr.table.n)
8105 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8106 else
8107 target = curproxy;
8108
8109 if (!target) {
8110 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8111 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8112 http_trk_idx(hrqrule->action));
8113 cfgerr++;
8114 }
8115 else if (target->table.size == 0) {
8116 Alert("Proxy '%s': table '%s' used but not configured.\n",
8117 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8118 cfgerr++;
8119 }
8120 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8121 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8122 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8123 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008124 cfgerr++;
8125 }
8126 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008127 free(hrqrule->arg.trk_ctr.table.n);
8128 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008129 /* Note: if we decide to enhance the track-sc syntax, we may be able
8130 * to pass a list of counters to track and allocate them right here using
8131 * stktable_alloc_data_type().
8132 */
8133 }
8134 }
8135
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008136 /* move any "block" rules at the beginning of the http-request rules */
8137 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8138 /* insert block_rules into http_req_rules at the beginning */
8139 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8140 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8141 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8142 curproxy->http_req_rules.n = curproxy->block_rules.n;
8143 LIST_INIT(&curproxy->block_rules);
8144 }
8145
Emeric Brun32da3c42010-09-23 18:39:19 +02008146 if (curproxy->table.peers.name) {
8147 struct peers *curpeers = peers;
8148
8149 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8150 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8151 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008152 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008153 break;
8154 }
8155 }
8156
8157 if (!curpeers) {
8158 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8159 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008160 free((void *)curproxy->table.peers.name);
8161 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008162 cfgerr++;
8163 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008164 else if (curpeers->state == PR_STSTOPPED) {
8165 /* silently disable this peers section */
8166 curproxy->table.peers.p = NULL;
8167 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008168 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008169 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8170 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008171 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008172 cfgerr++;
8173 }
8174 }
8175
Simon Horman9dc49962015-01-30 11:22:59 +09008176
8177 if (curproxy->email_alert.mailers.name) {
8178 struct mailers *curmailers = mailers;
8179
8180 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8181 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8182 free(curproxy->email_alert.mailers.name);
8183 curproxy->email_alert.mailers.m = curmailers;
8184 curmailers->users++;
8185 break;
8186 }
8187 }
8188
8189 if (!curmailers) {
8190 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8191 curproxy->id, curproxy->email_alert.mailers.name);
8192 free_email_alert(curproxy);
8193 cfgerr++;
8194 }
8195 }
8196
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008197 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008198 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008199 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8200 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8201 "proxy", curproxy->id);
8202 cfgerr++;
8203 goto out_uri_auth_compat;
8204 }
8205
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008206 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008207 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008208 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008209 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008210
Willy Tarreau95fa4692010-02-01 13:05:50 +01008211 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8212 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008213
8214 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008215 uri_auth_compat_req[i++] = "realm";
8216 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8217 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008218
Willy Tarreau95fa4692010-02-01 13:05:50 +01008219 uri_auth_compat_req[i++] = "unless";
8220 uri_auth_compat_req[i++] = "{";
8221 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8222 uri_auth_compat_req[i++] = "}";
8223 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008224
Willy Tarreauff011f22011-01-06 17:51:27 +01008225 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8226 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008227 cfgerr++;
8228 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008229 }
8230
Willy Tarreauff011f22011-01-06 17:51:27 +01008231 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008232
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008233 if (curproxy->uri_auth->auth_realm) {
8234 free(curproxy->uri_auth->auth_realm);
8235 curproxy->uri_auth->auth_realm = NULL;
8236 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008237
8238 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008239 }
8240out_uri_auth_compat:
8241
Dragan Dosen43885c72015-10-01 13:18:13 +02008242 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008243 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008244 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8245 if (!curproxy->conf.logformat_sd_string) {
8246 /* set the default logformat_sd_string */
8247 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8248 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008249 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008250 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008251 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008252
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008253 /* compile the log format */
8254 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008255 if (curproxy->conf.logformat_string != default_http_log_format &&
8256 curproxy->conf.logformat_string != default_tcp_log_format &&
8257 curproxy->conf.logformat_string != clf_http_log_format)
8258 free(curproxy->conf.logformat_string);
8259 curproxy->conf.logformat_string = NULL;
8260 free(curproxy->conf.lfs_file);
8261 curproxy->conf.lfs_file = NULL;
8262 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008263
8264 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8265 free(curproxy->conf.logformat_sd_string);
8266 curproxy->conf.logformat_sd_string = NULL;
8267 free(curproxy->conf.lfsd_file);
8268 curproxy->conf.lfsd_file = NULL;
8269 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008270 }
8271
Willy Tarreau62a61232013-04-12 18:13:46 +02008272 if (curproxy->conf.logformat_string) {
8273 curproxy->conf.args.ctx = ARGC_LOG;
8274 curproxy->conf.args.file = curproxy->conf.lfs_file;
8275 curproxy->conf.args.line = curproxy->conf.lfs_line;
8276 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008277 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008278 curproxy->conf.args.file = NULL;
8279 curproxy->conf.args.line = 0;
8280 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008281
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008282 if (curproxy->conf.logformat_sd_string) {
8283 curproxy->conf.args.ctx = ARGC_LOGSD;
8284 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8285 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8286 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8287 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8288 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8289 curproxy->conf.args.file = NULL;
8290 curproxy->conf.args.line = 0;
8291 }
8292
Willy Tarreau62a61232013-04-12 18:13:46 +02008293 if (curproxy->conf.uniqueid_format_string) {
8294 curproxy->conf.args.ctx = ARGC_UIF;
8295 curproxy->conf.args.file = curproxy->conf.uif_file;
8296 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008297 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008298 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008299 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008300 curproxy->conf.args.file = NULL;
8301 curproxy->conf.args.line = 0;
8302 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008303
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008304 /* only now we can check if some args remain unresolved.
8305 * This must be done after the users and groups resolution.
8306 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008307 cfgerr += smp_resolve_args(curproxy);
8308 if (!cfgerr)
8309 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008310
Willy Tarreau2738a142006-07-08 17:28:09 +02008311 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008312 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008313 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008314 (!curproxy->timeout.connect ||
8315 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008316 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008317 " | While not properly invalid, you will certainly encounter various problems\n"
8318 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008319 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008320 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008321 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008322 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008323
Willy Tarreau1fa31262007-12-03 00:36:16 +01008324 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8325 * We must still support older configurations, so let's find out whether those
8326 * parameters have been set or must be copied from contimeouts.
8327 */
8328 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008329 if (!curproxy->timeout.tarpit ||
8330 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008331 /* tarpit timeout not set. We search in the following order:
8332 * default.tarpit, curr.connect, default.connect.
8333 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008334 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008335 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008336 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008337 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008338 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008339 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008340 }
8341 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008342 (!curproxy->timeout.queue ||
8343 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008344 /* queue timeout not set. We search in the following order:
8345 * default.queue, curr.connect, default.connect.
8346 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008347 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008348 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008349 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008350 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008351 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008352 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008353 }
8354 }
8355
Willy Tarreau1620ec32011-08-06 17:05:02 +02008356 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008357 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008358 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008359 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008360 }
8361
Willy Tarreau215663d2014-06-13 18:30:23 +02008362 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8363 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8364 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8365 proxy_type_str(curproxy), curproxy->id);
8366 err_code |= ERR_WARN;
8367 }
8368
Willy Tarreau193b8c62012-11-22 00:17:38 +01008369 /* ensure that cookie capture length is not too large */
8370 if (curproxy->capture_len >= global.tune.cookie_len) {
8371 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8372 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8373 err_code |= ERR_WARN;
8374 curproxy->capture_len = global.tune.cookie_len - 1;
8375 }
8376
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008377 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008378 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008379 curproxy->req_cap_pool = create_pool("ptrcap",
8380 curproxy->nb_req_cap * sizeof(char *),
8381 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008382 }
8383
8384 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008385 curproxy->rsp_cap_pool = create_pool("ptrcap",
8386 curproxy->nb_rsp_cap * sizeof(char *),
8387 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008388 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008389
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008390 switch (curproxy->load_server_state_from_file) {
8391 case PR_SRV_STATE_FILE_UNSPEC:
8392 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8393 break;
8394 case PR_SRV_STATE_FILE_GLOBAL:
8395 if (!global.server_state_file) {
8396 Warning("config : backend '%s' configured to load server state file from global section 'server-state-file' directive. Unfortunately, 'server-state-file' is not set!\n",
8397 curproxy->id);
8398 err_code |= ERR_WARN;
8399 }
8400 break;
8401 }
8402
Willy Tarreaubaaee002006-06-26 02:48:02 +02008403 /* first, we will invert the servers list order */
8404 newsrv = NULL;
8405 while (curproxy->srv) {
8406 struct server *next;
8407
8408 next = curproxy->srv->next;
8409 curproxy->srv->next = newsrv;
8410 newsrv = curproxy->srv;
8411 if (!next)
8412 break;
8413 curproxy->srv = next;
8414 }
8415
Willy Tarreau17edc812014-01-03 12:14:34 +01008416 /* Check that no server name conflicts. This causes trouble in the stats.
8417 * We only emit a warning for the first conflict affecting each server,
8418 * in order to avoid combinatory explosion if all servers have the same
8419 * name. We do that only for servers which do not have an explicit ID,
8420 * because these IDs were made also for distinguishing them and we don't
8421 * want to annoy people who correctly manage them.
8422 */
8423 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8424 struct server *other_srv;
8425
8426 if (newsrv->puid)
8427 continue;
8428
8429 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8430 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8431 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8432 newsrv->conf.file, newsrv->conf.line,
8433 proxy_type_str(curproxy), curproxy->id,
8434 newsrv->id, other_srv->conf.line);
8435 break;
8436 }
8437 }
8438 }
8439
Willy Tarreaudd701652010-05-25 23:03:02 +02008440 /* assign automatic UIDs to servers which don't have one yet */
8441 next_id = 1;
8442 newsrv = curproxy->srv;
8443 while (newsrv != NULL) {
8444 if (!newsrv->puid) {
8445 /* server ID not set, use automatic numbering with first
8446 * spare entry starting with next_svid.
8447 */
8448 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8449 newsrv->conf.id.key = newsrv->puid = next_id;
8450 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8451 }
8452 next_id++;
8453 newsrv = newsrv->next;
8454 }
8455
Willy Tarreau20697042007-11-15 23:26:18 +01008456 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008457 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008458
Willy Tarreau62c3be22012-01-20 13:12:32 +01008459 /*
8460 * If this server supports a maxconn parameter, it needs a dedicated
8461 * tasks to fill the emptied slots when a connection leaves.
8462 * Also, resolve deferred tracking dependency if needed.
8463 */
8464 newsrv = curproxy->srv;
8465 while (newsrv != NULL) {
8466 if (newsrv->minconn > newsrv->maxconn) {
8467 /* Only 'minconn' was specified, or it was higher than or equal
8468 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8469 * this will avoid further useless expensive computations.
8470 */
8471 newsrv->maxconn = newsrv->minconn;
8472 } else if (newsrv->maxconn && !newsrv->minconn) {
8473 /* minconn was not specified, so we set it to maxconn */
8474 newsrv->minconn = newsrv->maxconn;
8475 }
8476
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008477#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008478 if (newsrv->use_ssl || newsrv->check.use_ssl)
8479 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008480#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008481
Willy Tarreau2f075e92013-12-03 11:11:34 +01008482 /* set the check type on the server */
8483 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8484
Willy Tarreau62c3be22012-01-20 13:12:32 +01008485 if (newsrv->trackit) {
8486 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008487 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008488 char *pname, *sname;
8489
8490 pname = newsrv->trackit;
8491 sname = strrchr(pname, '/');
8492
8493 if (sname)
8494 *sname++ = '\0';
8495 else {
8496 sname = pname;
8497 pname = NULL;
8498 }
8499
8500 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008501 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008502 if (!px) {
8503 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8504 proxy_type_str(curproxy), curproxy->id,
8505 newsrv->id, pname);
8506 cfgerr++;
8507 goto next_srv;
8508 }
8509 } else
8510 px = curproxy;
8511
8512 srv = findserver(px, sname);
8513 if (!srv) {
8514 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8515 proxy_type_str(curproxy), curproxy->id,
8516 newsrv->id, sname);
8517 cfgerr++;
8518 goto next_srv;
8519 }
8520
Willy Tarreau32091232014-05-16 13:52:00 +02008521 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8522 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8523 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008524 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008525 "tracking as it does not have any check nor agent enabled.\n",
8526 proxy_type_str(curproxy), curproxy->id,
8527 newsrv->id, px->id, srv->id);
8528 cfgerr++;
8529 goto next_srv;
8530 }
8531
8532 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8533
8534 if (loop) {
8535 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8536 "belongs to a tracking chain looping back to %s/%s.\n",
8537 proxy_type_str(curproxy), curproxy->id,
8538 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008539 cfgerr++;
8540 goto next_srv;
8541 }
8542
8543 if (curproxy != px &&
8544 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8545 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8546 "tracking: disable-on-404 option inconsistency.\n",
8547 proxy_type_str(curproxy), curproxy->id,
8548 newsrv->id, px->id, srv->id);
8549 cfgerr++;
8550 goto next_srv;
8551 }
8552
Willy Tarreau62c3be22012-01-20 13:12:32 +01008553 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008554 newsrv->tracknext = srv->trackers;
8555 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008556
8557 free(newsrv->trackit);
8558 newsrv->trackit = NULL;
8559 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008560
8561 /*
8562 * resolve server's resolvers name and update the resolvers pointer
8563 * accordingly
8564 */
8565 if (newsrv->resolvers_id) {
8566 struct dns_resolvers *curr_resolvers;
8567 int found;
8568
8569 found = 0;
8570 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8571 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8572 found = 1;
8573 break;
8574 }
8575 }
8576
8577 if (!found) {
8578 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8579 proxy_type_str(curproxy), curproxy->id,
8580 newsrv->id, newsrv->resolvers_id);
8581 cfgerr++;
8582 } else {
8583 free(newsrv->resolvers_id);
8584 newsrv->resolvers_id = NULL;
8585 if (newsrv->resolution)
8586 newsrv->resolution->resolvers = curr_resolvers;
8587 }
8588 }
8589 else {
8590 /* if no resolvers section associated to this server
8591 * we can clean up the associated resolution structure
8592 */
8593 if (newsrv->resolution) {
8594 free(newsrv->resolution->hostname_dn);
8595 newsrv->resolution->hostname_dn = NULL;
8596 free(newsrv->resolution);
8597 newsrv->resolution = NULL;
8598 }
8599 }
8600
Willy Tarreau62c3be22012-01-20 13:12:32 +01008601 next_srv:
8602 newsrv = newsrv->next;
8603 }
8604
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008605 /* We have to initialize the server lookup mechanism depending
8606 * on what LB algorithm was choosen.
8607 */
8608
8609 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8610 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8611 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008612 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8613 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8614 init_server_map(curproxy);
8615 } else {
8616 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8617 fwrr_init_server_groups(curproxy);
8618 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008619 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008620
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008621 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008622 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8623 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8624 fwlc_init_server_tree(curproxy);
8625 } else {
8626 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8627 fas_init_server_tree(curproxy);
8628 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008629 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008630
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008631 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008632 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8633 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8634 chash_init_server_tree(curproxy);
8635 } else {
8636 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8637 init_server_map(curproxy);
8638 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008639 break;
8640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008641
8642 if (curproxy->options & PR_O_LOGASAP)
8643 curproxy->to_log &= ~LW_BYTES;
8644
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008645 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008646 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8647 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008648 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8649 proxy_type_str(curproxy), curproxy->id);
8650 err_code |= ERR_WARN;
8651 }
8652
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008653 if (curproxy->mode != PR_MODE_HTTP) {
8654 int optnum;
8655
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008656 if (curproxy->uri_auth) {
8657 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8658 proxy_type_str(curproxy), curproxy->id);
8659 err_code |= ERR_WARN;
8660 curproxy->uri_auth = NULL;
8661 }
8662
Willy Tarreau87cf5142011-08-19 22:57:24 +02008663 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008664 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8665 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8666 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008667 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008668 }
8669
8670 if (curproxy->options & PR_O_ORGTO) {
8671 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8672 "originalto", proxy_type_str(curproxy), curproxy->id);
8673 err_code |= ERR_WARN;
8674 curproxy->options &= ~PR_O_ORGTO;
8675 }
8676
8677 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8678 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8679 (curproxy->cap & cfg_opts[optnum].cap) &&
8680 (curproxy->options & cfg_opts[optnum].val)) {
8681 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8682 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8683 err_code |= ERR_WARN;
8684 curproxy->options &= ~cfg_opts[optnum].val;
8685 }
8686 }
8687
8688 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8689 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8690 (curproxy->cap & cfg_opts2[optnum].cap) &&
8691 (curproxy->options2 & cfg_opts2[optnum].val)) {
8692 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8693 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8694 err_code |= ERR_WARN;
8695 curproxy->options2 &= ~cfg_opts2[optnum].val;
8696 }
8697 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008698
Willy Tarreau29fbe512015-08-20 19:35:14 +02008699#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008700 if (curproxy->conn_src.bind_hdr_occ) {
8701 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008702 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008703 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008704 err_code |= ERR_WARN;
8705 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008706#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008707 }
8708
Willy Tarreaubaaee002006-06-26 02:48:02 +02008709 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008710 * ensure that we're not cross-dressing a TCP server into HTTP.
8711 */
8712 newsrv = curproxy->srv;
8713 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008714 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008715 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8716 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008717 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008718 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008719
Willy Tarreau0cec3312011-10-31 13:49:26 +01008720 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8721 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8722 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8723 err_code |= ERR_WARN;
8724 }
8725
Willy Tarreauc93cd162014-05-13 15:54:22 +02008726 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008727 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8728 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8729 err_code |= ERR_WARN;
8730 }
8731
Willy Tarreau29fbe512015-08-20 19:35:14 +02008732#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008733 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8734 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008735 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 +01008736 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008737 err_code |= ERR_WARN;
8738 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008739#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008740 newsrv = newsrv->next;
8741 }
8742
Willy Tarreaue42bd962014-09-16 16:21:19 +02008743 /* check if we have a frontend with "tcp-request content" looking at L7
8744 * with no inspect-delay
8745 */
8746 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8747 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008748 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008749 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008750 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008751 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008752 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008753 break;
8754 }
8755
8756 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8757 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8758 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8759 " This means that these rules will randomly find their contents. This can be fixed by"
8760 " setting the tcp-request inspect-delay.\n",
8761 proxy_type_str(curproxy), curproxy->id);
8762 err_code |= ERR_WARN;
8763 }
8764 }
8765
Christopher Fauletd7c91962015-04-30 11:48:27 +02008766 /* Check filter configuration, if any */
8767 cfgerr += flt_check(curproxy);
8768
Willy Tarreauc1a21672009-08-16 22:37:44 +02008769 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008770 if (!curproxy->accept)
8771 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008772
Willy Tarreauc1a21672009-08-16 22:37:44 +02008773 if (curproxy->tcp_req.inspect_delay ||
8774 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008775 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008776
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008777 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008778 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008779 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008780 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008781
8782 /* both TCP and HTTP must check switching rules */
8783 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008784
8785 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008786 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008787 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8788 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008789 if (curproxy->mode == PR_MODE_HTTP) {
8790 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8791 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8792 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008793 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008794 }
8795
8796 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008797 if (curproxy->tcp_req.inspect_delay ||
8798 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8799 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8800
Emeric Brun97679e72010-09-23 17:56:44 +02008801 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8802 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8803
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008804 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008805 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008806 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008807 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008808
8809 /* If the backend does requires RDP cookie persistence, we have to
8810 * enable the corresponding analyser.
8811 */
8812 if (curproxy->options2 & PR_O2_RDPC_PRST)
8813 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008814
8815 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008816 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008817 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8818 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008819 if (curproxy->mode == PR_MODE_HTTP) {
8820 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8821 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8822 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008823 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008824 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008825 }
8826
8827 /***********************************************************/
8828 /* At this point, target names have already been resolved. */
8829 /***********************************************************/
8830
8831 /* Check multi-process mode compatibility */
8832
8833 if (global.nbproc > 1 && global.stats_fe) {
8834 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8835 unsigned long mask;
8836
8837 mask = nbits(global.nbproc);
8838 if (global.stats_fe->bind_proc)
8839 mask &= global.stats_fe->bind_proc;
8840
8841 if (bind_conf->bind_proc)
8842 mask &= bind_conf->bind_proc;
8843
8844 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008845 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008846 break;
8847 }
8848 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8849 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");
8850 }
8851 }
8852
8853 /* Make each frontend inherit bind-process from its listeners when not specified. */
8854 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8855 if (curproxy->bind_proc)
8856 continue;
8857
8858 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8859 unsigned long mask;
8860
Willy Tarreaue428b082015-05-04 21:57:58 +02008861 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008862 curproxy->bind_proc |= mask;
8863 }
8864
8865 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008866 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008867 }
8868
8869 if (global.stats_fe) {
8870 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8871 unsigned long mask;
8872
Cyril Bonté06181952016-02-24 00:14:54 +01008873 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008874 global.stats_fe->bind_proc |= mask;
8875 }
8876 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008877 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008878 }
8879
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008880 /* propagate bindings from frontends to backends. Don't do it if there
8881 * are any fatal errors as we must not call it with unresolved proxies.
8882 */
8883 if (!cfgerr) {
8884 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8885 if (curproxy->cap & PR_CAP_FE)
8886 propagate_processes(curproxy, NULL);
8887 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008888 }
8889
8890 /* Bind each unbound backend to all processes when not specified. */
8891 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8892 if (curproxy->bind_proc)
8893 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008894 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008895 }
8896
8897 /*******************************************************/
8898 /* At this step, all proxies have a non-null bind_proc */
8899 /*******************************************************/
8900
8901 /* perform the final checks before creating tasks */
8902
8903 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8904 struct listener *listener;
8905 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008906
Emeric Brunc52962f2012-11-15 18:28:02 +01008907#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008908 /* Configure SSL for each bind line.
8909 * Note: if configuration fails at some point, the ->ctx member
8910 * remains NULL so that listeners can later detach.
8911 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008912 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008913 int alloc_ctx;
8914
Emeric Brunc52962f2012-11-15 18:28:02 +01008915 if (!bind_conf->is_ssl) {
8916 if (bind_conf->default_ctx) {
8917 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8918 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8919 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008920 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008921 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008922 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008923 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008924 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008925 cfgerr++;
8926 continue;
8927 }
8928
Emeric Brun8dc60392014-05-09 13:52:00 +02008929 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008930 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008931 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8932 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");
8933 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008934 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008935 cfgerr++;
8936 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008937 }
8938
Emeric Brunfc0421f2012-09-07 17:30:07 +02008939 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008940 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008941
8942 /* initialize CA variables if the certificates generation is enabled */
8943 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008944 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008945#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008946
Willy Tarreaue6b98942007-10-29 01:09:36 +01008947 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008948 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008949 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008950 int nbproc;
8951
8952 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008953 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008954 nbits(global.nbproc));
8955
8956 if (!nbproc) /* no intersection between listener and frontend */
8957 nbproc = 1;
8958
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008959 if (!listener->luid) {
8960 /* listener ID not set, use automatic numbering with first
8961 * spare entry starting with next_luid.
8962 */
8963 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8964 listener->conf.id.key = listener->luid = next_id;
8965 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008966 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008967 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008968
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008969 /* enable separate counters */
8970 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008971 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008972 if (!listener->name)
8973 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008974 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008975
Willy Tarreaue6b98942007-10-29 01:09:36 +01008976 if (curproxy->options & PR_O_TCP_NOLING)
8977 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008978 if (!listener->maxconn)
8979 listener->maxconn = curproxy->maxconn;
8980 if (!listener->backlog)
8981 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008982 if (!listener->maxaccept)
8983 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8984
8985 /* we want to have an optimal behaviour on single process mode to
8986 * maximize the work at once, but in multi-process we want to keep
8987 * some fairness between processes, so we target half of the max
8988 * number of events to be balanced over all the processes the proxy
8989 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8990 * used to disable the limit.
8991 */
8992 if (listener->maxaccept > 0) {
8993 if (nbproc > 1)
8994 listener->maxaccept = (listener->maxaccept + 1) / 2;
8995 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8996 }
8997
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008998 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008999 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009000 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009001 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009002
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009003 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009004 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009005
Willy Tarreau620408f2016-10-21 16:37:51 +02009006 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9007 listener->options |= LI_O_TCP_L5_RULES;
9008
Willy Tarreaude3041d2010-05-31 10:56:17 +02009009 if (curproxy->mon_mask.s_addr)
9010 listener->options |= LI_O_CHK_MONNET;
9011
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009012 /* smart accept mode is automatic in HTTP mode */
9013 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009014 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009015 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9016 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009017 }
9018
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009019 /* Release unused SSL configs */
9020 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
9021 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009022 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009023#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02009024 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009025 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009026 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02009027 free(bind_conf->ca_sign_file);
9028 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009029 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02009030 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009031 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009032 if(bind_conf->keys_ref) {
9033 free(bind_conf->keys_ref->filename);
9034 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02009035 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009036 free(bind_conf->keys_ref);
9037 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009038#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009039 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009040
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009041 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009042 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009043 int count, maxproc = 0;
9044
9045 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009046 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009047 if (count > maxproc)
9048 maxproc = count;
9049 }
9050 /* backends have 0, frontends have 1 or more */
9051 if (maxproc != 1)
9052 Warning("Proxy '%s': in multi-process mode, stats will be"
9053 " limited to process assigned to the current request.\n",
9054 curproxy->id);
9055
Willy Tarreau102df612014-05-07 23:56:38 +02009056 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9057 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9058 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009059 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009060 }
Willy Tarreau102df612014-05-07 23:56:38 +02009061 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9062 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9063 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009064 }
9065 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009066
9067 /* create the task associated with the proxy */
9068 curproxy->task = task_new();
9069 if (curproxy->task) {
9070 curproxy->task->context = curproxy;
9071 curproxy->task->process = manage_proxy;
9072 /* no need to queue, it will be done automatically if some
9073 * listener gets limited.
9074 */
9075 curproxy->task->expire = TICK_ETERNITY;
9076 } else {
9077 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9078 curproxy->id);
9079 cfgerr++;
9080 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009081 }
9082
Willy Tarreaufbb78422011-06-05 15:38:35 +02009083 /* automatically compute fullconn if not set. We must not do it in the
9084 * loop above because cross-references are not yet fully resolved.
9085 */
9086 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9087 /* If <fullconn> is not set, let's set it to 10% of the sum of
9088 * the possible incoming frontend's maxconns.
9089 */
9090 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9091 struct proxy *fe;
9092 int total = 0;
9093
9094 /* sum up the number of maxconns of frontends which
9095 * reference this backend at least once or which are
9096 * the same one ('listen').
9097 */
9098 for (fe = proxy; fe; fe = fe->next) {
9099 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009100 int found = 0;
9101
9102 if (!(fe->cap & PR_CAP_FE))
9103 continue;
9104
9105 if (fe == curproxy) /* we're on a "listen" instance */
9106 found = 1;
9107
9108 if (fe->defbe.be == curproxy) /* "default_backend" */
9109 found = 1;
9110
9111 /* check if a "use_backend" rule matches */
9112 if (!found) {
9113 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009114 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009115 found = 1;
9116 break;
9117 }
9118 }
9119 }
9120
Willy Tarreaufbb78422011-06-05 15:38:35 +02009121 /* now we've checked all possible ways to reference a backend
9122 * from a frontend.
9123 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009124 if (!found)
9125 continue;
9126 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009127 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009128 /* we have the sum of the maxconns in <total>. We only
9129 * keep 10% of that sum to set the default fullconn, with
9130 * a hard minimum of 1 (to avoid a divide by zero).
9131 */
9132 curproxy->fullconn = (total + 9) / 10;
9133 if (!curproxy->fullconn)
9134 curproxy->fullconn = 1;
9135 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009136 }
9137
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009138 /*
9139 * Recount currently required checks.
9140 */
9141
9142 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9143 int optnum;
9144
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009145 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9146 if (curproxy->options & cfg_opts[optnum].val)
9147 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009148
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009149 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9150 if (curproxy->options2 & cfg_opts2[optnum].val)
9151 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009152 }
9153
Willy Tarreau0fca4832015-05-01 19:12:05 +02009154 /* compute the required process bindings for the peers */
9155 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9156 if (curproxy->table.peers.p)
9157 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9158
Willy Tarreau122541c2011-09-07 21:24:49 +02009159 if (peers) {
9160 struct peers *curpeers = peers, **last;
9161 struct peer *p, *pb;
9162
Willy Tarreau1e273012015-05-01 19:15:17 +02009163 /* Remove all peers sections which don't have a valid listener,
9164 * which are not used by any table, or which are bound to more
9165 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009166 */
9167 last = &peers;
9168 while (*last) {
9169 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009170
9171 if (curpeers->state == PR_STSTOPPED) {
9172 /* the "disabled" keyword was present */
9173 if (curpeers->peers_fe)
9174 stop_proxy(curpeers->peers_fe);
9175 curpeers->peers_fe = NULL;
9176 }
9177 else if (!curpeers->peers_fe) {
9178 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9179 curpeers->id, localpeer);
9180 }
David Carliere6c39412015-07-02 07:00:17 +00009181 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009182 /* either it's totally stopped or too much used */
9183 if (curpeers->peers_fe->bind_proc) {
9184 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009185 "running in different processes (%d different ones). "
9186 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009187 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009188 cfgerr++;
9189 }
9190 stop_proxy(curpeers->peers_fe);
9191 curpeers->peers_fe = NULL;
9192 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009193 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009194 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009195 last = &curpeers->next;
9196 continue;
9197 }
9198
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009199 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009200 p = curpeers->remote;
9201 while (p) {
9202 pb = p->next;
9203 free(p->id);
9204 free(p);
9205 p = pb;
9206 }
9207
9208 /* Destroy and unlink this curpeers section.
9209 * Note: curpeers is backed up into *last.
9210 */
9211 free(curpeers->id);
9212 curpeers = curpeers->next;
9213 free(*last);
9214 *last = curpeers;
9215 }
9216 }
9217
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009218 /* initialize stick-tables on backend capable proxies. This must not
9219 * be done earlier because the data size may be discovered while parsing
9220 * other proxies.
9221 */
9222 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9223 if (curproxy->state == PR_STSTOPPED)
9224 continue;
9225
9226 if (!stktable_init(&curproxy->table)) {
9227 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9228 cfgerr++;
9229 }
9230 }
9231
Simon Horman0d16a402015-01-30 11:22:58 +09009232 if (mailers) {
9233 struct mailers *curmailers = mailers, **last;
9234 struct mailer *m, *mb;
9235
9236 /* Remove all mailers sections which don't have a valid listener.
9237 * This can happen when a mailers section is never referenced.
9238 */
9239 last = &mailers;
9240 while (*last) {
9241 curmailers = *last;
9242 if (curmailers->users) {
9243 last = &curmailers->next;
9244 continue;
9245 }
9246
9247 Warning("Removing incomplete section 'mailers %s'.\n",
9248 curmailers->id);
9249
9250 m = curmailers->mailer_list;
9251 while (m) {
9252 mb = m->next;
9253 free(m->id);
9254 free(m);
9255 m = mb;
9256 }
9257
9258 /* Destroy and unlink this curmailers section.
9259 * Note: curmailers is backed up into *last.
9260 */
9261 free(curmailers->id);
9262 curmailers = curmailers->next;
9263 free(*last);
9264 *last = curmailers;
9265 }
9266 }
9267
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009268 /* Update server_state_file_name to backend name if backend is supposed to use
9269 * a server-state file locally defined and none has been provided */
9270 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9271 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9272 curproxy->server_state_file_name == NULL)
9273 curproxy->server_state_file_name = strdup(curproxy->id);
9274 }
9275
Willy Tarreau34eb6712011-10-24 18:15:04 +02009276 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009277 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009278 MEM_F_SHARED);
9279
Willy Tarreaubb925012009-07-23 13:36:36 +02009280 if (cfgerr > 0)
9281 err_code |= ERR_ALERT | ERR_FATAL;
9282 out:
9283 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009284}
9285
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009286/*
9287 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9288 * parsing sessions.
9289 */
9290void cfg_register_keywords(struct cfg_kw_list *kwl)
9291{
9292 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9293}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009294
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009295/*
9296 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9297 */
9298void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9299{
9300 LIST_DEL(&kwl->list);
9301 LIST_INIT(&kwl->list);
9302}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009303
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009304/* this function register new section in the haproxy configuration file.
9305 * <section_name> is the name of this new section and <section_parser>
9306 * is the called parser. If two section declaration have the same name,
9307 * only the first declared is used.
9308 */
9309int cfg_register_section(char *section_name,
9310 int (*section_parser)(const char *, int, char **, int))
9311{
9312 struct cfg_section *cs;
9313
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009314 list_for_each_entry(cs, &sections, list) {
9315 if (strcmp(cs->section_name, section_name) == 0) {
9316 Alert("register section '%s': already registered.\n", section_name);
9317 return 0;
9318 }
9319 }
9320
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009321 cs = calloc(1, sizeof(*cs));
9322 if (!cs) {
9323 Alert("register section '%s': out of memory.\n", section_name);
9324 return 0;
9325 }
9326
9327 cs->section_name = section_name;
9328 cs->section_parser = section_parser;
9329
9330 LIST_ADDQ(&sections, &cs->list);
9331
9332 return 1;
9333}
9334
Willy Tarreaubaaee002006-06-26 02:48:02 +02009335/*
David Carlier845efb52015-09-25 11:49:18 +01009336 * free all config section entries
9337 */
9338void cfg_unregister_sections(void)
9339{
9340 struct cfg_section *cs, *ics;
9341
9342 list_for_each_entry_safe(cs, ics, &sections, list) {
9343 LIST_DEL(&cs->list);
9344 free(cs);
9345 }
9346}
9347
Christopher Faulet7110b402016-10-26 11:09:44 +02009348void cfg_backup_sections(struct list *backup_sections)
9349{
9350 struct cfg_section *cs, *ics;
9351
9352 list_for_each_entry_safe(cs, ics, &sections, list) {
9353 LIST_DEL(&cs->list);
9354 LIST_ADDQ(backup_sections, &cs->list);
9355 }
9356}
9357
9358void cfg_restore_sections(struct list *backup_sections)
9359{
9360 struct cfg_section *cs, *ics;
9361
9362 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9363 LIST_DEL(&cs->list);
9364 LIST_ADDQ(&sections, &cs->list);
9365 }
9366}
9367
Willy Tarreau659fbf02016-05-26 17:55:28 +02009368__attribute__((constructor))
9369static void cfgparse_init(void)
9370{
9371 /* Register internal sections */
9372 cfg_register_section("listen", cfg_parse_listen);
9373 cfg_register_section("frontend", cfg_parse_listen);
9374 cfg_register_section("backend", cfg_parse_listen);
9375 cfg_register_section("defaults", cfg_parse_listen);
9376 cfg_register_section("global", cfg_parse_global);
9377 cfg_register_section("userlist", cfg_parse_users);
9378 cfg_register_section("peers", cfg_parse_peers);
9379 cfg_register_section("mailers", cfg_parse_mailers);
9380 cfg_register_section("namespace_list", cfg_parse_netns);
9381 cfg_register_section("resolvers", cfg_parse_resolvers);
9382}
9383
David Carlier845efb52015-09-25 11:49:18 +01009384/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009385 * Local variables:
9386 * c-indent-level: 8
9387 * c-basic-offset: 8
9388 * End:
9389 */