blob: 35ae7b65b601f56735ff6d81c6d529ec9db7f562 [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 Tarreaud39ad442016-11-25 15:16:12 +0100480/* report a warning if a redirect rule is dangerously placed */
481int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200482{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100483 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200484 warnif_rule_after_use_server(proxy, file, line, arg);
485}
486
Willy Tarreaud39ad442016-11-25 15:16:12 +0100487/* report a warning if a reqadd rule is dangerously placed */
488int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200489{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100490 return warnif_rule_after_redirect(proxy, file, line, arg) ||
491 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200492}
493
Willy Tarreaud39ad442016-11-25 15:16:12 +0100494/* report a warning if a reqxxx rule is dangerously placed */
495int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200496{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100497 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
498 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200499}
500
501/* report a warning if an http-request rule is dangerously placed */
502int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
503{
Willy Tarreau61d18892009-03-31 10:49:21 +0200504 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100505 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200506}
507
Willy Tarreaud39ad442016-11-25 15:16:12 +0100508/* report a warning if a block rule is dangerously placed */
509int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200510{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100511 return warnif_rule_after_http_req(proxy, file, line, arg) ||
512 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200513}
514
Willy Tarreaud39ad442016-11-25 15:16:12 +0100515/* report a warning if a "tcp request content" rule is dangerously placed */
516int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200517{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100518 return warnif_rule_after_block(proxy, file, line, arg) ||
519 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200520}
521
Willy Tarreaud39ad442016-11-25 15:16:12 +0100522/* report a warning if a "tcp request session" rule is dangerously placed */
523int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200524{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
526 warnif_misplaced_tcp_cont(proxy, file, line, arg);
527}
528
529/* report a warning if a "tcp request connection" rule is dangerously placed */
530int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
531{
532 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
533 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200534}
535
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100536/* Report it if a request ACL condition uses some keywords that are incompatible
537 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
538 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
539 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100540 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100541static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100543 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200544 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100545
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100546 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100547 return 0;
548
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100549 acl = acl_cond_conflicts(cond, where);
550 if (acl) {
551 if (acl->name && *acl->name)
552 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
553 file, line, acl->name, sample_ckp_names(where));
554 else
555 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 +0200556 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100557 return ERR_WARN;
558 }
559 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100560 return 0;
561
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100562 if (acl->name && *acl->name)
563 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200564 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100565 else
566 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200567 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100568 return ERR_WARN;
569}
570
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200572 * parse a line in a <global> section. Returns the error code, 0 if OK, or
573 * any combination of :
574 * - ERR_ABORT: must abort ASAP
575 * - ERR_FATAL: we can continue parsing but not start the service
576 * - ERR_WARN: a warning has been emitted
577 * - ERR_ALERT: an alert has been emitted
578 * Only the two first ones can stop processing, the two others are just
579 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200581int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582{
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200584 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585
586 if (!strcmp(args[0], "global")) { /* new section */
587 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200588 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200591 else if (!strcmp(args[0], "ca-base")) {
592#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200593 if(alertif_too_many_args(1, file, linenum, args, &err_code))
594 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200595 if (global.ca_base != NULL) {
596 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT;
598 goto out;
599 }
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.ca_base = strdup(args[1]);
606#else
607 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610#endif
611 }
612 else if (!strcmp(args[0], "crt-base")) {
613#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200614 if (alertif_too_many_args(1, file, linenum, args, &err_code))
615 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200616 if (global.crt_base != NULL) {
617 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT;
619 goto out;
620 }
621 if (*(args[1]) == 0) {
622 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
623 err_code |= ERR_ALERT | ERR_FATAL;
624 goto out;
625 }
626 global.crt_base = strdup(args[1]);
627#else
628 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631#endif
632 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200634 if (alertif_too_many_args(0, file, linenum, args, &err_code))
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 global.mode |= MODE_DAEMON;
637 }
638 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(0, file, linenum, args, &err_code))
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 global.mode |= MODE_DEBUG;
642 }
643 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200644 if (alertif_too_many_args(0, file, linenum, args, &err_code))
645 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100646 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200648 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200649 if (alertif_too_many_args(0, file, linenum, args, &err_code))
650 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100651 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200654 if (alertif_too_many_args(0, file, linenum, args, &err_code))
655 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100656 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100658 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100661 global.tune.options &= ~GTUNE_USE_SPLICE;
662 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200663 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200666 global.tune.options &= ~GTUNE_USE_GAI;
667 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000668 else if (!strcmp(args[0], "noreuseport")) {
669 if (alertif_too_many_args(0, file, linenum, args, &err_code))
670 goto out;
671 global.tune.options &= ~GTUNE_USE_REUSEPORT;
672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200674 if (alertif_too_many_args(0, file, linenum, args, &err_code))
675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 global.mode |= MODE_QUIET;
677 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200678 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200679 if (alertif_too_many_args(1, file, linenum, args, &err_code))
680 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200681 if (global.tune.maxpollevents != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200690 }
691 global.tune.maxpollevents = atol(args[1]);
692 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100693 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200694 if (alertif_too_many_args(1, file, linenum, args, &err_code))
695 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100696 if (global.tune.maxaccept != 0) {
697 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 err_code |= ERR_ALERT;
699 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100700 }
701 if (*(args[1]) == 0) {
702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200703 err_code |= ERR_ALERT | ERR_FATAL;
704 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100705 }
706 global.tune.maxaccept = atol(args[1]);
707 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200708 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200709 if (alertif_too_many_args(1, file, linenum, args, &err_code))
710 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 global.tune.chksize = atol(args[1]);
717 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100718 else if (!strcmp(args[0], "tune.recv_enough")) {
719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
720 goto out;
721 if (*(args[1]) == 0) {
722 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
725 }
726 global.tune.recv_enough = atol(args[1]);
727 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200728#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200729 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200730 if (alertif_too_many_args(0, file, linenum, args, &err_code))
731 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200732 global.tune.sslprivatecache = 1;
733 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100734 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200735 if (alertif_too_many_args(1, file, linenum, args, &err_code))
736 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742 global.tune.sslcachesize = atol(args[1]);
743 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100744 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
745 unsigned int ssllifetime;
746 const char *res;
747
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755
756 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
757 if (res) {
758 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
759 file, linenum, *res, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763
764 global.tune.ssllifetime = ssllifetime;
765 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100766 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200767 if (alertif_too_many_args(1, file, linenum, args, &err_code))
768 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100769 if (*(args[1]) == 0) {
770 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
773 }
774 global.tune.ssl_max_record = atol(args[1]);
775 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200776#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200777 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200778 if (alertif_too_many_args(1, file, linenum, args, &err_code))
779 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 global.tune.ssl_default_dh_param = atol(args[1]);
786 if (global.tune.ssl_default_dh_param < 1024) {
787 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT | ERR_FATAL;
789 goto out;
790 }
791 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200792#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200793 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
794 if (alertif_too_many_args(1, file, linenum, args, &err_code))
795 goto out;
796 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_ctx_cache = atoi(args[1]);
802 if (global.tune.ssl_ctx_cache < 0) {
803 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
804 file, linenum, args[0]);
805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
807 }
808 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200809#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100810 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200811 if (alertif_too_many_args(1, file, linenum, args, &err_code))
812 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100813 if (*(args[1]) == 0) {
814 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 global.tune.buf_limit = atol(args[1]);
819 if (global.tune.buf_limit) {
820 if (global.tune.buf_limit < 3)
821 global.tune.buf_limit = 3;
822 if (global.tune.buf_limit <= global.tune.reserved_bufs)
823 global.tune.buf_limit = global.tune.reserved_bufs + 1;
824 }
825 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100826 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200827 if (alertif_too_many_args(1, file, linenum, args, &err_code))
828 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.reserved_bufs = atol(args[1]);
835 if (global.tune.reserved_bufs < 2)
836 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100837 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
838 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100839 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200840 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200841 if (alertif_too_many_args(1, file, linenum, args, &err_code))
842 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200843 if (*(args[1]) == 0) {
844 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
848 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200849 if (global.tune.bufsize <= 0) {
850 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100854 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100855 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200856 }
857 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200860 if (*(args[1]) == 0) {
861 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200866 if (global.tune.maxrewrite < 0) {
867 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200871 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100872 else if (!strcmp(args[0], "tune.idletimer")) {
873 unsigned int idle;
874 const char *res;
875
William Lallemand1a748ae2015-05-19 16:37:23 +0200876 if (alertif_too_many_args(1, file, linenum, args, &err_code))
877 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100878 if (*(args[1]) == 0) {
879 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883
884 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
885 if (res) {
886 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
887 file, linenum, *res, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891
892 if (idle > 65535) {
893 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
896 }
897 global.tune.idle_timer = idle;
898 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100899 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200900 if (alertif_too_many_args(1, file, linenum, args, &err_code))
901 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100902 if (global.tune.client_rcvbuf != 0) {
903 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
904 err_code |= ERR_ALERT;
905 goto out;
906 }
907 if (*(args[1]) == 0) {
908 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911 }
912 global.tune.client_rcvbuf = atol(args[1]);
913 }
914 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200915 if (alertif_too_many_args(1, file, linenum, args, &err_code))
916 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100917 if (global.tune.server_rcvbuf != 0) {
918 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT;
920 goto out;
921 }
922 if (*(args[1]) == 0) {
923 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
924 err_code |= ERR_ALERT | ERR_FATAL;
925 goto out;
926 }
927 global.tune.server_rcvbuf = atol(args[1]);
928 }
929 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200930 if (alertif_too_many_args(1, file, linenum, args, &err_code))
931 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100932 if (global.tune.client_sndbuf != 0) {
933 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
934 err_code |= ERR_ALERT;
935 goto out;
936 }
937 if (*(args[1]) == 0) {
938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942 global.tune.client_sndbuf = atol(args[1]);
943 }
944 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200945 if (alertif_too_many_args(1, file, linenum, args, &err_code))
946 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100947 if (global.tune.server_sndbuf != 0) {
948 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT;
950 goto out;
951 }
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957 global.tune.server_sndbuf = atol(args[1]);
958 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200959 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200960 if (alertif_too_many_args(1, file, linenum, args, &err_code))
961 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 global.tune.pipesize = atol(args[1]);
968 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100969 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200970 if (alertif_too_many_args(1, file, linenum, args, &err_code))
971 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100972 if (*(args[1]) == 0) {
973 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 global.tune.cookie_len = atol(args[1]) + 1;
978 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200979 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200980 if (alertif_too_many_args(1, file, linenum, args, &err_code))
981 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200982 if (*(args[1]) == 0) {
983 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987 global.tune.max_http_hdr = atol(args[1]);
988 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100989 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
990#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200991 if (alertif_too_many_args(1, file, linenum, args, &err_code))
992 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100993 if (*args[1]) {
994 global.tune.zlibmemlevel = atoi(args[1]);
995 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
996 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
997 file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 } else {
1002 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1003 file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007#else
1008 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011#endif
1012 }
1013 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1014#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001015 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1016 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001017 if (*args[1]) {
1018 global.tune.zlibwindowsize = atoi(args[1]);
1019 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1020 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1021 file, linenum, args[0]);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025 } else {
1026 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1027 file, linenum, args[0]);
1028 err_code |= ERR_ALERT | ERR_FATAL;
1029 goto out;
1030 }
1031#else
1032 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035#endif
1036 }
William Lallemandf3747832012-11-09 12:33:10 +01001037 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001038 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1039 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001040 if (*args[1]) {
1041 global.tune.comp_maxlevel = atoi(args[1]);
1042 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1043 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1044 file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 } else {
1049 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1050 file, linenum, args[0]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053 }
1054 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001055 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1056 if (*args[1]) {
1057 global.tune.pattern_cache = atoi(args[1]);
1058 if (global.tune.pattern_cache < 0) {
1059 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1060 file, linenum, args[0]);
1061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
1063 }
1064 } else {
1065 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1066 file, linenum, args[0]);
1067 err_code |= ERR_ALERT | ERR_FATAL;
1068 goto out;
1069 }
1070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001072 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001075 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001076 err_code |= ERR_ALERT;
1077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 }
1079 if (*(args[1]) == 0) {
1080 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001084 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1085 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]);
1086 err_code |= ERR_WARN;
1087 goto out;
1088 }
1089
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 }
1091 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001092 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001095 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001096 err_code |= ERR_ALERT;
1097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 }
1099 if (*(args[1]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001104 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1105 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]);
1106 err_code |= ERR_WARN;
1107 goto out;
1108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109 }
Simon Horman98637e52014-06-20 12:30:16 +09001110 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001111 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1112 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001113 global.external_check = 1;
1114 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001115 /* user/group name handling */
1116 else if (!strcmp(args[0], "user")) {
1117 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001118 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1119 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001120 if (global.uid != 0) {
1121 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT;
1123 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001124 }
1125 errno = 0;
1126 ha_user = getpwnam(args[1]);
1127 if (ha_user != NULL) {
1128 global.uid = (int)ha_user->pw_uid;
1129 }
1130 else {
1131 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 +02001132 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001133 }
1134 }
1135 else if (!strcmp(args[0], "group")) {
1136 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001137 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1138 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001139 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001140 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT;
1142 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001143 }
1144 errno = 0;
1145 ha_group = getgrnam(args[1]);
1146 if (ha_group != NULL) {
1147 global.gid = (int)ha_group->gr_gid;
1148 }
1149 else {
1150 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 +02001151 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001152 }
1153 }
1154 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001156 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 if (*(args[1]) == 0) {
1159 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 }
1163 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001164 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1165 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1166 file, linenum, args[0], LONGBITS, global.nbproc);
1167 err_code |= ERR_ALERT | ERR_FATAL;
1168 goto out;
1169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170 }
1171 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 if (global.maxconn != 0) {
1175 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 if (*(args[1]) == 0) {
1180 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 }
1184 global.maxconn = atol(args[1]);
1185#ifdef SYSTEM_MAXCONN
1186 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1187 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);
1188 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001189 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 }
1191#endif /* SYSTEM_MAXCONN */
1192 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001193 else if (!strcmp(args[0], "maxsslconn")) {
1194#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001195 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1196 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001197 if (*(args[1]) == 0) {
1198 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
1201 }
1202 global.maxsslconn = atol(args[1]);
1203#else
Emeric Brun0914df82012-10-02 18:45:42 +02001204 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001207#endif
1208 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001209 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1210#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001211 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1212 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218 free(global.listen_default_ciphers);
1219 global.listen_default_ciphers = strdup(args[1]);
1220#else
1221 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224#endif
1225 }
1226 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1227#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001228 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1229 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001230 if (*(args[1]) == 0) {
1231 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235 free(global.connect_default_ciphers);
1236 global.connect_default_ciphers = strdup(args[1]);
1237#else
1238 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1239 err_code |= ERR_ALERT | ERR_FATAL;
1240 goto out;
1241#endif
1242 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001243#ifdef USE_OPENSSL
1244#ifndef OPENSSL_NO_DH
1245 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1246 if (*(args[1]) == 0) {
1247 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250 }
1251 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1252 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1253 err_code |= ERR_ALERT | ERR_FATAL;
1254 goto out;
1255 }
1256 }
1257#endif
1258#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001259 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001260 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1261 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001262 if (*(args[1]) == 0) {
1263 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto out;
1266 }
1267 if (strcmp(args[1],"none") == 0)
1268 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1269 else if (strcmp(args[1],"required") == 0)
1270 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1271 else {
1272 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
1275 }
1276 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001277 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001280 if (global.cps_lim != 0) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1282 err_code |= ERR_ALERT;
1283 goto out;
1284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 global.cps_lim = atol(args[1]);
1291 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001292 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001293 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1294 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001295 if (global.sps_lim != 0) {
1296 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1297 err_code |= ERR_ALERT;
1298 goto out;
1299 }
1300 if (*(args[1]) == 0) {
1301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1302 err_code |= ERR_ALERT | ERR_FATAL;
1303 goto out;
1304 }
1305 global.sps_lim = atol(args[1]);
1306 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001307 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001308 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1309 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001310 if (global.ssl_lim != 0) {
1311 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1312 err_code |= ERR_ALERT;
1313 goto out;
1314 }
1315 if (*(args[1]) == 0) {
1316 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
1320 global.ssl_lim = atol(args[1]);
1321 }
William Lallemandd85f9172012-11-09 17:05:39 +01001322 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001323 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1324 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
1329 }
1330 global.comp_rate_lim = atoi(args[1]) * 1024;
1331 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001332 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001333 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1334 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001335 if (global.maxpipes != 0) {
1336 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001337 err_code |= ERR_ALERT;
1338 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001339 }
1340 if (*(args[1]) == 0) {
1341 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001344 }
1345 global.maxpipes = atol(args[1]);
1346 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001347 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001348 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1349 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001350 if (*(args[1]) == 0) {
1351 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
William Lallemande3a7d992012-11-20 11:25:20 +01001355 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001356 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001357 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001358 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1359 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001360 if (*(args[1]) == 0) {
1361 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364 }
1365 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001366 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001367 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
1370 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001371 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001372
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001374 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if (global.rlimit_nofile != 0) {
1377 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001378 err_code |= ERR_ALERT;
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
1381 if (*(args[1]) == 0) {
1382 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 }
1386 global.rlimit_nofile = atol(args[1]);
1387 }
1388 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001389 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 if (global.chroot != NULL) {
1392 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001393 err_code |= ERR_ALERT;
1394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 }
1396 if (*(args[1]) == 0) {
1397 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
1401 global.chroot = strdup(args[1]);
1402 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001403 else if (!strcmp(args[0], "description")) {
1404 int i, len=0;
1405 char *d;
1406
1407 if (!*args[1]) {
1408 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1409 file, linenum, args[0]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
1412 }
1413
Willy Tarreau348acfe2014-04-14 15:00:39 +02001414 for (i = 1; *args[i]; i++)
1415 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001416
1417 if (global.desc)
1418 free(global.desc);
1419
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001420 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001421
Willy Tarreau348acfe2014-04-14 15:00:39 +02001422 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1423 for (i = 2; *args[i]; i++)
1424 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001425 }
1426 else if (!strcmp(args[0], "node")) {
1427 int i;
1428 char c;
1429
William Lallemand1a748ae2015-05-19 16:37:23 +02001430 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1431 goto out;
1432
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001433 for (i=0; args[1][i]; i++) {
1434 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001435 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1436 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001437 break;
1438 }
1439
1440 if (!i || args[1][i]) {
1441 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1442 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1443 file, linenum, args[0]);
1444 err_code |= ERR_ALERT | ERR_FATAL;
1445 goto out;
1446 }
1447
1448 if (global.node)
1449 free(global.node);
1450
1451 global.node = strdup(args[1]);
1452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001454 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 if (global.pidfile != NULL) {
1457 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001458 err_code |= ERR_ALERT;
1459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 }
1461 if (*(args[1]) == 0) {
1462 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001463 err_code |= ERR_ALERT | ERR_FATAL;
1464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465 }
1466 global.pidfile = strdup(args[1]);
1467 }
Emeric Bruned760922010-10-22 17:59:25 +02001468 else if (!strcmp(args[0], "unix-bind")) {
1469 int cur_arg = 1;
1470 while (*(args[cur_arg])) {
1471 if (!strcmp(args[cur_arg], "prefix")) {
1472 if (global.unix_bind.prefix != NULL) {
1473 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1474 err_code |= ERR_ALERT;
1475 cur_arg += 2;
1476 continue;
1477 }
1478
1479 if (*(args[cur_arg+1]) == 0) {
1480 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
1483 }
1484 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1485 cur_arg += 2;
1486 continue;
1487 }
1488
1489 if (!strcmp(args[cur_arg], "mode")) {
1490
1491 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1492 cur_arg += 2;
1493 continue;
1494 }
1495
1496 if (!strcmp(args[cur_arg], "uid")) {
1497
1498 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1499 cur_arg += 2;
1500 continue;
1501 }
1502
1503 if (!strcmp(args[cur_arg], "gid")) {
1504
1505 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1506 cur_arg += 2;
1507 continue;
1508 }
1509
1510 if (!strcmp(args[cur_arg], "user")) {
1511 struct passwd *user;
1512
1513 user = getpwnam(args[cur_arg + 1]);
1514 if (!user) {
1515 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1516 file, linenum, args[0], args[cur_arg + 1 ]);
1517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520
1521 global.unix_bind.ux.uid = user->pw_uid;
1522 cur_arg += 2;
1523 continue;
1524 }
1525
1526 if (!strcmp(args[cur_arg], "group")) {
1527 struct group *group;
1528
1529 group = getgrnam(args[cur_arg + 1]);
1530 if (!group) {
1531 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1532 file, linenum, args[0], args[cur_arg + 1 ]);
1533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
1535 }
1536
1537 global.unix_bind.ux.gid = group->gr_gid;
1538 cur_arg += 2;
1539 continue;
1540 }
1541
Willy Tarreaub48f9582011-09-05 01:17:06 +02001542 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001543 file, linenum, args[0]);
1544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
1547 }
William Lallemand0f99e342011-10-12 17:50:54 +02001548 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1549 /* delete previous herited or defined syslog servers */
1550 struct logsrv *back;
1551 struct logsrv *tmp;
1552
1553 if (*(args[1]) != 0) {
1554 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557 }
1558
1559 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1560 LIST_DEL(&tmp->list);
1561 free(tmp);
1562 }
1563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001565 struct sockaddr_storage *sk;
1566 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001567 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001568 int arg = 0;
1569 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001570
William Lallemand1a748ae2015-05-19 16:37:23 +02001571 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1572 goto out;
1573
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 if (*(args[1]) == 0 || *(args[2]) == 0) {
1575 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
William Lallemand0f99e342011-10-12 17:50:54 +02001579
Vincent Bernat02779b62016-04-03 13:48:43 +02001580 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001581
Willy Tarreau18324f52014-06-27 18:10:07 +02001582 /* just after the address, a length may be specified */
1583 if (strcmp(args[arg+2], "len") == 0) {
1584 len = atoi(args[arg+3]);
1585 if (len < 80 || len > 65535) {
1586 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1587 file, linenum, args[arg+3]);
1588 err_code |= ERR_ALERT | ERR_FATAL;
1589 goto out;
1590 }
1591 logsrv->maxlen = len;
1592
1593 /* skip these two args */
1594 arg += 2;
1595 }
1596 else
1597 logsrv->maxlen = MAX_SYSLOG_LEN;
1598
1599 if (logsrv->maxlen > global.max_syslog_len) {
1600 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001601 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1602 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1603 logline = my_realloc2(logline, global.max_syslog_len + 1);
1604 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001605 }
1606
Dragan Dosen1322d092015-09-22 16:05:32 +02001607 /* after the length, a format may be specified */
1608 if (strcmp(args[arg+2], "format") == 0) {
1609 logsrv->format = get_log_format(args[arg+3]);
1610 if (logsrv->format < 0) {
1611 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1612 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001613 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001614 goto out;
1615 }
1616
1617 /* skip these two args */
1618 arg += 2;
1619 }
1620
David Carlier97880bb2016-04-08 10:35:26 +01001621 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1622 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001623 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001624 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001625
Willy Tarreau18324f52014-06-27 18:10:07 +02001626 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001627 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001628 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001630 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 }
1632
William Lallemand0f99e342011-10-12 17:50:54 +02001633 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001634 if (*(args[arg+3])) {
1635 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001636 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001637 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001639 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 }
1641 }
1642
William Lallemand0f99e342011-10-12 17:50:54 +02001643 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001644 if (*(args[arg+4])) {
1645 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001646 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001647 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001648 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001649 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001650 }
1651 }
1652
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001653 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001654 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001655 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001656 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001657 free(logsrv);
1658 goto out;
1659 }
1660 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001661
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001662 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001663 if (port1 != port2) {
1664 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1665 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001666 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001667 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001668 goto out;
1669 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001670
William Lallemand0f99e342011-10-12 17:50:54 +02001671 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001672 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001673 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675
William Lallemand0f99e342011-10-12 17:50:54 +02001676 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001677 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001678 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1679 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001680
1681 if (global.log_send_hostname != NULL) {
1682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1683 err_code |= ERR_ALERT;
1684 goto out;
1685 }
1686
1687 if (*(args[1]))
1688 name = args[1];
1689 else
1690 name = hostname;
1691
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001692 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001693 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001694 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001695 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1696 if (global.server_state_base != NULL) {
1697 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1698 err_code |= ERR_ALERT;
1699 goto out;
1700 }
1701
1702 if (!*(args[1])) {
1703 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1704 err_code |= ERR_FATAL;
1705 goto out;
1706 }
1707
1708 global.server_state_base = strdup(args[1]);
1709 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001710 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1711 if (global.server_state_file != NULL) {
1712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1713 err_code |= ERR_ALERT;
1714 goto out;
1715 }
1716
1717 if (!*(args[1])) {
1718 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1719 err_code |= ERR_FATAL;
1720 goto out;
1721 }
1722
1723 global.server_state_file = strdup(args[1]);
1724 }
Kevinm48936af2010-12-22 16:08:21 +00001725 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001726 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1727 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001728 if (*(args[1]) == 0) {
1729 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
1732 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001733 chunk_destroy(&global.log_tag);
1734 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001735 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001736 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001737 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1738 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001739 if (global.spread_checks != 0) {
1740 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001741 err_code |= ERR_ALERT;
1742 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001743 }
1744 if (*(args[1]) == 0) {
1745 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001746 err_code |= ERR_ALERT | ERR_FATAL;
1747 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001748 }
1749 global.spread_checks = atol(args[1]);
1750 if (global.spread_checks < 0 || global.spread_checks > 50) {
1751 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001752 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001753 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001755 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1756 const char *err;
1757 unsigned int val;
1758
William Lallemand1a748ae2015-05-19 16:37:23 +02001759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1760 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001761 if (*(args[1]) == 0) {
1762 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
1765 }
1766
1767 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1768 if (err) {
1769 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 }
1772 global.max_spread_checks = val;
1773 if (global.max_spread_checks < 0) {
1774 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1775 err_code |= ERR_ALERT | ERR_FATAL;
1776 }
1777 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001778 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1779#ifdef USE_CPU_AFFINITY
1780 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001781 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001782 unsigned long cpus = 0;
1783
1784 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001785 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001786 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001787 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001788 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001789 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001790 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001791 proc = atol(args[1]);
1792 if (proc >= 1 && proc <= LONGBITS)
1793 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001794 }
1795
1796 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001797 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",
1798 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
1801 }
1802
1803 cur_arg = 2;
1804 while (*args[cur_arg]) {
1805 unsigned int low, high;
1806
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001807 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001808 char *dash = strchr(args[cur_arg], '-');
1809
1810 low = high = str2uic(args[cur_arg]);
1811 if (dash)
1812 high = str2uic(dash + 1);
1813
1814 if (high < low) {
1815 unsigned int swap = low;
1816 low = high;
1817 high = swap;
1818 }
1819
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001820 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001821 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001822 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
1825 }
1826
1827 while (low <= high)
1828 cpus |= 1UL << low++;
1829 }
1830 else {
1831 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1832 file, linenum, args[0], args[cur_arg]);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836 cur_arg++;
1837 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001838 for (i = 0; i < LONGBITS; i++)
1839 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001840 global.cpu_map[i] = cpus;
1841#else
1842 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
1845#endif
1846 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001847 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1848 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1849 goto out;
1850
1851 if (*(args[2]) == 0) {
1852 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
1857 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1858 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1859 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
1862 }
1863 }
1864 else if (!strcmp(args[0], "unsetenv")) {
1865 int arg;
1866
1867 if (*(args[1]) == 0) {
1868 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872
1873 for (arg = 1; *args[arg]; arg++) {
1874 if (unsetenv(args[arg]) != 0) {
1875 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879 }
1880 }
1881 else if (!strcmp(args[0], "resetenv")) {
1882 extern char **environ;
1883 char **env = environ;
1884
1885 /* args contain variable names to keep, one per argument */
1886 while (*env) {
1887 int arg;
1888
1889 /* look for current variable in among all those we want to keep */
1890 for (arg = 1; *args[arg]; arg++) {
1891 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1892 (*env)[strlen(args[arg])] == '=')
1893 break;
1894 }
1895
1896 /* delete this variable */
1897 if (!*args[arg]) {
1898 char *delim = strchr(*env, '=');
1899
1900 if (!delim || delim - *env >= trash.size) {
1901 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
1904 }
1905
1906 memcpy(trash.str, *env, delim - *env);
1907 trash.str[delim - *env] = 0;
1908
1909 if (unsetenv(trash.str) != 0) {
1910 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
1913 }
1914 }
1915 else
1916 env++;
1917 }
1918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001920 struct cfg_kw_list *kwl;
1921 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001922 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001923
1924 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1925 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1926 if (kwl->kw[index].section != CFG_GLOBAL)
1927 continue;
1928 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001929 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001930 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001931 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001933 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001934 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001935 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001936 err_code |= ERR_WARN;
1937 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001938 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001939 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001940 }
1941 }
1942 }
1943
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001945 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001947
Willy Tarreau058e9072009-07-20 09:30:05 +02001948 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001949 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001950 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001951}
1952
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001953void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001955 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 defproxy.mode = PR_MODE_TCP;
1957 defproxy.state = PR_STNEW;
1958 defproxy.maxconn = cfg_maxpconn;
1959 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001960 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001961 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001962
Simon Horman66183002013-02-23 10:16:43 +09001963 defproxy.defsrv.check.inter = DEF_CHKINTR;
1964 defproxy.defsrv.check.fastinter = 0;
1965 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001966 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1967 defproxy.defsrv.agent.fastinter = 0;
1968 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001969 defproxy.defsrv.check.rise = DEF_RISETIME;
1970 defproxy.defsrv.check.fall = DEF_FALLTIME;
1971 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1972 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001973 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001974 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001975 defproxy.defsrv.maxqueue = 0;
1976 defproxy.defsrv.minconn = 0;
1977 defproxy.defsrv.maxconn = 0;
1978 defproxy.defsrv.slowstart = 0;
1979 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1980 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1981 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001982
1983 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001984 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985}
1986
Willy Tarreauade5ec42010-01-28 19:33:49 +01001987
Willy Tarreau63af98d2014-05-18 08:11:41 +02001988/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1989 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1990 * ERR_FATAL in case of error.
1991 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001992static int create_cond_regex_rule(const char *file, int line,
1993 struct proxy *px, int dir, int action, int flags,
1994 const char *cmd, const char *reg, const char *repl,
1995 const char **cond_start)
1996{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001997 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001998 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001999 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002000 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002001 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002002 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002003 int cs;
2004 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002005
2006 if (px == &defproxy) {
2007 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002008 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002009 goto err;
2010 }
2011
2012 if (*reg == 0) {
2013 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002014 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002015 goto err;
2016 }
2017
Christopher Faulet898566e2016-10-26 11:06:28 +02002018 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002019 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002020
Willy Tarreau5321c422010-01-28 20:35:13 +01002021 if (cond_start &&
2022 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002023 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2024 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2025 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002026 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002027 goto err;
2028 }
2029 }
2030 else if (cond_start && **cond_start) {
2031 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2032 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002033 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002034 goto err;
2035 }
2036
Willy Tarreau63af98d2014-05-18 08:11:41 +02002037 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002038 (dir == SMP_OPT_DIR_REQ) ?
2039 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2040 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2041 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002042
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002043 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002044 if (!preg) {
2045 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002046 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002047 goto err;
2048 }
2049
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002050 cs = !(flags & REG_ICASE);
2051 cap = !(flags & REG_NOSUB);
2052 error = NULL;
2053 if (!regex_comp(reg, preg, cs, cap, &error)) {
2054 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2055 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002056 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002057 goto err;
2058 }
2059
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002060 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002061 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002062 if (repl && err) {
2063 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2064 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002065 ret_code |= ERR_ALERT | ERR_FATAL;
2066 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002067 }
2068
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002069 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002070 ret_code |= ERR_WARN;
2071
2072 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002073
Willy Tarreau63af98d2014-05-18 08:11:41 +02002074 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002075 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002076 err:
2077 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002078 free(errmsg);
2079 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002080}
2081
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082/*
William Lallemand51097192015-04-14 16:35:22 +02002083 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002084 * Returns the error code, 0 if OK, or any combination of :
2085 * - ERR_ABORT: must abort ASAP
2086 * - ERR_FATAL: we can continue parsing but not start the service
2087 * - ERR_WARN: a warning has been emitted
2088 * - ERR_ALERT: an alert has been emitted
2089 * Only the two first ones can stop processing, the two others are just
2090 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002092int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2093{
2094 static struct peers *curpeers = NULL;
2095 struct peer *newpeer = NULL;
2096 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002097 struct bind_conf *bind_conf;
2098 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002099 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002100 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002101
2102 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002103 if (!*args[1]) {
2104 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002105 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002106 goto out;
2107 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002108
William Lallemand6e62fb62015-04-28 16:55:23 +02002109 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2110 goto out;
2111
Emeric Brun32da3c42010-09-23 18:39:19 +02002112 err = invalid_char(args[1]);
2113 if (err) {
2114 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2115 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002116 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002117 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002118 }
2119
2120 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2121 /*
2122 * If there are two proxies with the same name only following
2123 * combinations are allowed:
2124 */
2125 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002126 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 +02002127 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002128 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002129 }
2130 }
2131
Vincent Bernat02779b62016-04-03 13:48:43 +02002132 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002133 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2134 err_code |= ERR_ALERT | ERR_ABORT;
2135 goto out;
2136 }
2137
2138 curpeers->next = peers;
2139 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002140 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002141 curpeers->conf.line = linenum;
2142 curpeers->last_change = now.tv_sec;
2143 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002144 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002145 }
2146 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002147 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002148 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002149 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002150
2151 if (!*args[2]) {
2152 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2153 file, linenum, args[0]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
2157
2158 err = invalid_char(args[1]);
2159 if (err) {
2160 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2161 file, linenum, *err, args[1]);
2162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
2164 }
2165
Vincent Bernat02779b62016-04-03 13:48:43 +02002166 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002167 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2168 err_code |= ERR_ALERT | ERR_ABORT;
2169 goto out;
2170 }
2171
2172 /* the peers are linked backwards first */
2173 curpeers->count++;
2174 newpeer->next = curpeers->remote;
2175 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002176 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002177 newpeer->conf.line = linenum;
2178
2179 newpeer->last_change = now.tv_sec;
2180 newpeer->id = strdup(args[1]);
2181
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002182 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002183 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002184 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002187 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002188
2189 proto = protocol_by_family(sk->ss_family);
2190 if (!proto || !proto->connect) {
2191 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2192 file, linenum, args[0], args[1]);
2193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
2195 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002196
2197 if (port1 != port2) {
2198 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2199 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
Willy Tarreau2aa38802013-02-20 19:20:59 +01002204 if (!port1) {
2205 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2206 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002210
Emeric Brun32da3c42010-09-23 18:39:19 +02002211 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002212 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002213 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002214 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002215
Emeric Brun32da3c42010-09-23 18:39:19 +02002216 if (strcmp(newpeer->id, localpeer) == 0) {
2217 /* Current is local peer, it define a frontend */
2218 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002219 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002220
2221 if (!curpeers->peers_fe) {
2222 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2224 err_code |= ERR_ALERT | ERR_ABORT;
2225 goto out;
2226 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002227
Willy Tarreau237250c2011-07-29 01:49:03 +02002228 init_new_proxy(curpeers->peers_fe);
2229 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002230 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002231 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2232 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002233 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002234
2235 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2236
Willy Tarreau902636f2013-03-10 19:44:48 +01002237 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2238 if (errmsg && *errmsg) {
2239 indent_msg(&errmsg, 2);
2240 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002241 }
2242 else
2243 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2244 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002245 err_code |= ERR_FATAL;
2246 goto out;
2247 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002248
2249 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002250 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002251 l->maxconn = curpeers->peers_fe->maxconn;
2252 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002253 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002254 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002255 l->analysers |= curpeers->peers_fe->fe_req_ana;
2256 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002257 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2258 global.maxsock += l->maxconn;
2259 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002260 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002261 else {
2262 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2263 file, linenum, args[0], args[1],
2264 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2265 err_code |= ERR_FATAL;
2266 goto out;
2267 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002268 }
2269 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002270 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2271 curpeers->state = PR_STSTOPPED;
2272 }
2273 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2274 curpeers->state = PR_STNEW;
2275 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002276 else if (*args[0] != 0) {
2277 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
2280 }
2281
2282out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002283 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002284 return err_code;
2285}
2286
Baptiste Assmann325137d2015-04-13 23:40:55 +02002287/*
2288 * Parse a <resolvers> section.
2289 * Returns the error code, 0 if OK, or any combination of :
2290 * - ERR_ABORT: must abort ASAP
2291 * - ERR_FATAL: we can continue parsing but not start the service
2292 * - ERR_WARN: a warning has been emitted
2293 * - ERR_ALERT: an alert has been emitted
2294 * Only the two first ones can stop processing, the two others are just
2295 * indicators.
2296 */
2297int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2298{
2299 static struct dns_resolvers *curr_resolvers = NULL;
2300 struct dns_nameserver *newnameserver = NULL;
2301 const char *err;
2302 int err_code = 0;
2303 char *errmsg = NULL;
2304
2305 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2306 if (!*args[1]) {
2307 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2308 err_code |= ERR_ALERT | ERR_ABORT;
2309 goto out;
2310 }
2311
2312 err = invalid_char(args[1]);
2313 if (err) {
2314 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2315 file, linenum, *err, args[0], args[1]);
2316 err_code |= ERR_ALERT | ERR_ABORT;
2317 goto out;
2318 }
2319
2320 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2321 /* Error if two resolvers owns the same name */
2322 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2323 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2324 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2325 err_code |= ERR_ALERT | ERR_ABORT;
2326 }
2327 }
2328
Vincent Bernat02779b62016-04-03 13:48:43 +02002329 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002330 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2331 err_code |= ERR_ALERT | ERR_ABORT;
2332 goto out;
2333 }
2334
2335 /* default values */
2336 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2337 curr_resolvers->conf.file = strdup(file);
2338 curr_resolvers->conf.line = linenum;
2339 curr_resolvers->id = strdup(args[1]);
2340 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002341 /* default hold period for nx, other, refuse and timeout is 30s */
2342 curr_resolvers->hold.nx = 30000;
2343 curr_resolvers->hold.other = 30000;
2344 curr_resolvers->hold.refused = 30000;
2345 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002346 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002347 curr_resolvers->hold.valid = 10000;
2348 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002349 curr_resolvers->resolve_retries = 3;
2350 LIST_INIT(&curr_resolvers->nameserver_list);
2351 LIST_INIT(&curr_resolvers->curr_resolution);
2352 }
2353 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2354 struct sockaddr_storage *sk;
2355 int port1, port2;
2356 struct protocol *proto;
2357
2358 if (!*args[2]) {
2359 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2360 file, linenum, args[0]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364
2365 err = invalid_char(args[1]);
2366 if (err) {
2367 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2368 file, linenum, *err, args[1]);
2369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
2371 }
2372
Baptiste Assmanna315c552015-11-02 22:55:49 +01002373 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2374 /* Error if two resolvers owns the same name */
2375 if (strcmp(newnameserver->id, args[1]) == 0) {
2376 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2377 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2378 err_code |= ERR_ALERT | ERR_FATAL;
2379 }
2380 }
2381
Vincent Bernat02779b62016-04-03 13:48:43 +02002382 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002383 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2384 err_code |= ERR_ALERT | ERR_ABORT;
2385 goto out;
2386 }
2387
2388 /* the nameservers are linked backward first */
2389 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2390 curr_resolvers->count_nameservers++;
2391 newnameserver->resolvers = curr_resolvers;
2392 newnameserver->conf.file = strdup(file);
2393 newnameserver->conf.line = linenum;
2394 newnameserver->id = strdup(args[1]);
2395
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002396 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002397 if (!sk) {
2398 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
2401 }
2402
2403 proto = protocol_by_family(sk->ss_family);
2404 if (!proto || !proto->connect) {
2405 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2406 file, linenum, args[0], args[1]);
2407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
2409 }
2410
2411 if (port1 != port2) {
2412 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2413 file, linenum, args[0], args[1], args[2]);
2414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
2416 }
2417
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002418 if (!port1 && !port2) {
2419 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2420 file, linenum, args[0], args[1]);
2421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
2423 }
2424
Baptiste Assmann325137d2015-04-13 23:40:55 +02002425 newnameserver->addr = *sk;
2426 }
2427 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2428 const char *res;
2429 unsigned int time;
2430
2431 if (!*args[2]) {
2432 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2433 file, linenum, args[0]);
2434 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2439 if (res) {
2440 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2441 file, linenum, *res, args[0]);
2442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
2444 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002445 if (strcmp(args[1], "nx") == 0)
2446 curr_resolvers->hold.nx = time;
2447 else if (strcmp(args[1], "other") == 0)
2448 curr_resolvers->hold.other = time;
2449 else if (strcmp(args[1], "refused") == 0)
2450 curr_resolvers->hold.refused = time;
2451 else if (strcmp(args[1], "timeout") == 0)
2452 curr_resolvers->hold.timeout = time;
2453 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002454 curr_resolvers->hold.valid = time;
2455 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002456 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2457 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
2460 }
2461
2462 }
2463 else if (strcmp(args[0], "resolve_retries") == 0) {
2464 if (!*args[1]) {
2465 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2466 file, linenum, args[0]);
2467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
2469 }
2470 curr_resolvers->resolve_retries = atoi(args[1]);
2471 }
2472 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002473 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002474 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2475 file, linenum, args[0]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002479 else if (strcmp(args[1], "retry") == 0) {
2480 const char *res;
2481 unsigned int timeout_retry;
2482
2483 if (!*args[2]) {
2484 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2485 file, linenum, args[0], args[1]);
2486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
2488 }
2489 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2490 if (res) {
2491 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2492 file, linenum, *res, args[0], args[1]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496 curr_resolvers->timeout.retry = timeout_retry;
2497 }
2498 else {
2499 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2500 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002504 } /* neither "nameserver" nor "resolvers" */
2505 else if (*args[0] != 0) {
2506 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
2509 }
2510
2511 out:
2512 free(errmsg);
2513 return err_code;
2514}
Simon Horman0d16a402015-01-30 11:22:58 +09002515
2516/*
William Lallemand51097192015-04-14 16:35:22 +02002517 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002518 * Returns the error code, 0 if OK, or any combination of :
2519 * - ERR_ABORT: must abort ASAP
2520 * - ERR_FATAL: we can continue parsing but not start the service
2521 * - ERR_WARN: a warning has been emitted
2522 * - ERR_ALERT: an alert has been emitted
2523 * Only the two first ones can stop processing, the two others are just
2524 * indicators.
2525 */
2526int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2527{
2528 static struct mailers *curmailers = NULL;
2529 struct mailer *newmailer = NULL;
2530 const char *err;
2531 int err_code = 0;
2532 char *errmsg = NULL;
2533
2534 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2535 if (!*args[1]) {
2536 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2537 err_code |= ERR_ALERT | ERR_ABORT;
2538 goto out;
2539 }
2540
2541 err = invalid_char(args[1]);
2542 if (err) {
2543 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2544 file, linenum, *err, args[0], args[1]);
2545 err_code |= ERR_ALERT | ERR_ABORT;
2546 goto out;
2547 }
2548
2549 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2550 /*
2551 * If there are two proxies with the same name only following
2552 * combinations are allowed:
2553 */
2554 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002555 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 +09002556 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002558 }
2559 }
2560
Vincent Bernat02779b62016-04-03 13:48:43 +02002561 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002562 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2563 err_code |= ERR_ALERT | ERR_ABORT;
2564 goto out;
2565 }
2566
2567 curmailers->next = mailers;
2568 mailers = curmailers;
2569 curmailers->conf.file = strdup(file);
2570 curmailers->conf.line = linenum;
2571 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002572 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2573 * But need enough time so that timeouts don't occur
2574 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002575 }
2576 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2577 struct sockaddr_storage *sk;
2578 int port1, port2;
2579 struct protocol *proto;
2580
2581 if (!*args[2]) {
2582 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2583 file, linenum, args[0]);
2584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
2586 }
2587
2588 err = invalid_char(args[1]);
2589 if (err) {
2590 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2591 file, linenum, *err, args[1]);
2592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
2594 }
2595
Vincent Bernat02779b62016-04-03 13:48:43 +02002596 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002597 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2598 err_code |= ERR_ALERT | ERR_ABORT;
2599 goto out;
2600 }
2601
2602 /* the mailers are linked backwards first */
2603 curmailers->count++;
2604 newmailer->next = curmailers->mailer_list;
2605 curmailers->mailer_list = newmailer;
2606 newmailer->mailers = curmailers;
2607 newmailer->conf.file = strdup(file);
2608 newmailer->conf.line = linenum;
2609
2610 newmailer->id = strdup(args[1]);
2611
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002612 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002613 if (!sk) {
2614 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
2617 }
2618
2619 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002620 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2621 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002622 file, linenum, args[0], args[1]);
2623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
2625 }
2626
2627 if (port1 != port2) {
2628 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2629 file, linenum, args[0], args[1], args[2]);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633
2634 if (!port1) {
2635 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2636 file, linenum, args[0], args[1], args[2]);
2637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
2639 }
2640
2641 newmailer->addr = *sk;
2642 newmailer->proto = proto;
2643 newmailer->xprt = &raw_sock;
2644 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002645 }
2646 else if (strcmp(args[0], "timeout") == 0) {
2647 if (!*args[1]) {
2648 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2649 file, linenum, args[0]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653 else if (strcmp(args[1], "mail") == 0) {
2654 const char *res;
2655 unsigned int timeout_mail;
2656 if (!*args[2]) {
2657 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2658 file, linenum, args[0], args[1]);
2659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
2661 }
2662 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2663 if (res) {
2664 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2665 file, linenum, *res, args[0]);
2666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669 if (timeout_mail <= 0) {
2670 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674 curmailers->timeout.mail = timeout_mail;
2675 } else {
2676 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2677 file, linenum, args[0], args[1]);
2678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
2680 }
2681 }
Simon Horman0d16a402015-01-30 11:22:58 +09002682 else if (*args[0] != 0) {
2683 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2684 err_code |= ERR_ALERT | ERR_FATAL;
2685 goto out;
2686 }
2687
2688out:
2689 free(errmsg);
2690 return err_code;
2691}
2692
Simon Horman9dc49962015-01-30 11:22:59 +09002693static void free_email_alert(struct proxy *p)
2694{
2695 free(p->email_alert.mailers.name);
2696 p->email_alert.mailers.name = NULL;
2697 free(p->email_alert.from);
2698 p->email_alert.from = NULL;
2699 free(p->email_alert.to);
2700 p->email_alert.to = NULL;
2701 free(p->email_alert.myhostname);
2702 p->email_alert.myhostname = NULL;
2703}
2704
Willy Tarreau3842f002009-06-14 11:39:52 +02002705int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706{
2707 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002708 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002709 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002710 int rc;
2711 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002712 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002713 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002714 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002715 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002716 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717
Willy Tarreau977b8e42006-12-29 14:19:17 +01002718 if (!strcmp(args[0], "listen"))
2719 rc = PR_CAP_LISTEN;
2720 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002721 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002722 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002723 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002724 else
2725 rc = PR_CAP_NONE;
2726
2727 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 if (!*args[1]) {
2729 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002730 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_ALERT | ERR_ABORT;
2733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002735
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002736 err = invalid_char(args[1]);
2737 if (err) {
2738 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2739 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002741 }
2742
Willy Tarreau8f50b682015-05-26 11:45:02 +02002743 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2744 if (curproxy) {
2745 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2746 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2747 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002749 }
2750
Vincent Bernat02779b62016-04-03 13:48:43 +02002751 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_ALERT | ERR_ABORT;
2754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002756
Willy Tarreau97cb7802010-01-03 20:23:58 +01002757 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 curproxy->next = proxy;
2759 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002760 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2761 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002762 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002764 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002765 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766
William Lallemand6e62fb62015-04-28 16:55:23 +02002767 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2768 if (curproxy->cap & PR_CAP_FE)
2769 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 }
2772
2773 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002774 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002775 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002776
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002779 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002780 curproxy->no_options = defproxy.no_options;
2781 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002782 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002783 curproxy->except_net = defproxy.except_net;
2784 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002785 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002786 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002788 if (defproxy.fwdfor_hdr_len) {
2789 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2790 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2791 }
2792
Willy Tarreaub86db342009-11-30 11:50:16 +01002793 if (defproxy.orgto_hdr_len) {
2794 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2795 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2796 }
2797
Mark Lamourinec2247f02012-01-04 13:02:01 -05002798 if (defproxy.server_id_hdr_len) {
2799 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2800 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2801 }
2802
Willy Tarreau977b8e42006-12-29 14:19:17 +01002803 if (curproxy->cap & PR_CAP_FE) {
2804 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002805 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002806 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002807
2808 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002809 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2810 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002811
2812 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002814
Willy Tarreau977b8e42006-12-29 14:19:17 +01002815 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002816 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002817 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002818 curproxy->fullconn = defproxy.fullconn;
2819 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002820 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002821 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002823 if (defproxy.check_req) {
2824 curproxy->check_req = calloc(1, defproxy.check_len);
2825 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2826 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002827 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002829 if (defproxy.expect_str) {
2830 curproxy->expect_str = strdup(defproxy.expect_str);
2831 if (defproxy.expect_regex) {
2832 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002833 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2834 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002835 }
2836 }
2837
Willy Tarreau67402132012-05-31 20:40:20 +02002838 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002839 if (defproxy.cookie_name)
2840 curproxy->cookie_name = strdup(defproxy.cookie_name);
2841 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002842 if (defproxy.cookie_domain)
2843 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002844
Willy Tarreau31936852010-10-06 16:59:56 +02002845 if (defproxy.cookie_maxidle)
2846 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2847
2848 if (defproxy.cookie_maxlife)
2849 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2850
Emeric Brun647caf12009-06-30 17:57:00 +02002851 if (defproxy.rdp_cookie_name)
2852 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2853 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2854
Willy Tarreau01732802007-11-01 22:48:15 +01002855 if (defproxy.url_param_name)
2856 curproxy->url_param_name = strdup(defproxy.url_param_name);
2857 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002858
Benoitaffb4812009-03-25 13:02:10 +01002859 if (defproxy.hh_name)
2860 curproxy->hh_name = strdup(defproxy.hh_name);
2861 curproxy->hh_len = defproxy.hh_len;
2862 curproxy->hh_match_domain = defproxy.hh_match_domain;
2863
Willy Tarreauef9a3602012-12-08 22:29:20 +01002864 if (defproxy.conn_src.iface_name)
2865 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2866 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002867 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002868#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002869 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002870#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002871 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002874 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002875 if (defproxy.capture_name)
2876 curproxy->capture_name = strdup(defproxy.capture_name);
2877 curproxy->capture_namelen = defproxy.capture_namelen;
2878 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002879 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880
Willy Tarreau977b8e42006-12-29 14:19:17 +01002881 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002882 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002883 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002884 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002885 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002886 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887 curproxy->mon_net = defproxy.mon_net;
2888 curproxy->mon_mask = defproxy.mon_mask;
2889 if (defproxy.monitor_uri)
2890 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2891 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002892 if (defproxy.defbe.name)
2893 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002894
2895 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002896 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2897 if (curproxy->conf.logformat_string &&
2898 curproxy->conf.logformat_string != default_http_log_format &&
2899 curproxy->conf.logformat_string != default_tcp_log_format &&
2900 curproxy->conf.logformat_string != clf_http_log_format)
2901 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2902
2903 if (defproxy.conf.lfs_file) {
2904 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2905 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2906 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002907
2908 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2909 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2910 if (curproxy->conf.logformat_sd_string &&
2911 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2912 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2913
2914 if (defproxy.conf.lfsd_file) {
2915 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2916 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002918 }
2919
2920 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002921 curproxy->timeout.connect = defproxy.timeout.connect;
2922 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002923 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002924 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002925 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002926 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002927 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002928 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002929 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002930 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002931 }
2932
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002934 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002935
2936 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002937 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002938 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002939 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002940 LIST_INIT(&node->list);
2941 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2942 }
2943
Willy Tarreau62a61232013-04-12 18:13:46 +02002944 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2945 if (curproxy->conf.uniqueid_format_string)
2946 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2947
Dragan Dosen43885c72015-10-01 13:18:13 +02002948 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002949
Willy Tarreau62a61232013-04-12 18:13:46 +02002950 if (defproxy.conf.uif_file) {
2951 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2952 curproxy->conf.uif_line = defproxy.conf.uif_line;
2953 }
William Lallemanda73203e2012-03-12 12:48:57 +01002954
2955 /* copy default header unique id */
2956 if (defproxy.header_unique_id)
2957 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2958
William Lallemand82fe75c2012-10-23 10:25:10 +02002959 /* default compression options */
2960 if (defproxy.comp != NULL) {
2961 curproxy->comp = calloc(1, sizeof(struct comp));
2962 curproxy->comp->algos = defproxy.comp->algos;
2963 curproxy->comp->types = defproxy.comp->types;
2964 }
2965
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002967 curproxy->conf.used_listener_id = EB_ROOT;
2968 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002969
Simon Horman98637e52014-06-20 12:30:16 +09002970 if (defproxy.check_path)
2971 curproxy->check_path = strdup(defproxy.check_path);
2972 if (defproxy.check_command)
2973 curproxy->check_command = strdup(defproxy.check_command);
2974
Simon Horman9dc49962015-01-30 11:22:59 +09002975 if (defproxy.email_alert.mailers.name)
2976 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2977 if (defproxy.email_alert.from)
2978 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2979 if (defproxy.email_alert.to)
2980 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2981 if (defproxy.email_alert.myhostname)
2982 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002983 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002984 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002985
Willy Tarreau93893792009-07-23 13:19:11 +02002986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 }
2988 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2989 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002990 /* FIXME-20070101: we should do this too at the end of the
2991 * config parsing to free all default values.
2992 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002993 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2994 err_code |= ERR_ABORT;
2995 goto out;
2996 }
2997
Willy Tarreaua534fea2008-08-03 12:19:50 +02002998 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002999 free(defproxy.check_command);
3000 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003001 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003002 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003003 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003004 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003005 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003006 free(defproxy.capture_name);
3007 free(defproxy.monitor_uri);
3008 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003009 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003010 free(defproxy.fwdfor_hdr_name);
3011 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003012 free(defproxy.orgto_hdr_name);
3013 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003014 free(defproxy.server_id_hdr_name);
3015 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003016 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003017 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003018 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003019 free(defproxy.expect_regex);
3020 defproxy.expect_regex = NULL;
3021 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003022
Willy Tarreau62a61232013-04-12 18:13:46 +02003023 if (defproxy.conf.logformat_string != default_http_log_format &&
3024 defproxy.conf.logformat_string != default_tcp_log_format &&
3025 defproxy.conf.logformat_string != clf_http_log_format)
3026 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003027
Willy Tarreau62a61232013-04-12 18:13:46 +02003028 free(defproxy.conf.uniqueid_format_string);
3029 free(defproxy.conf.lfs_file);
3030 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003031 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003032 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003033
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003034 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3035 free(defproxy.conf.logformat_sd_string);
3036 free(defproxy.conf.lfsd_file);
3037
Willy Tarreaua534fea2008-08-03 12:19:50 +02003038 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003039 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003040
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 /* we cannot free uri_auth because it might already be used */
3042 init_default_instance();
3043 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003044 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3045 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003046 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 }
3049 else if (curproxy == NULL) {
3050 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003054
3055 /* update the current file and line being parsed */
3056 curproxy->conf.args.file = curproxy->conf.file;
3057 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003058
3059 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003060 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3061 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3062 if (err_code & ERR_FATAL)
3063 goto out;
3064 }
3065 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003066 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003067 int cur_arg;
3068
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003074 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003075 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076
Willy Tarreau24709282013-03-10 21:32:12 +01003077 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003078 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003083
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003084 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003085
3086 /* use default settings for unix sockets */
3087 bind_conf->ux.uid = global.unix_bind.ux.uid;
3088 bind_conf->ux.gid = global.unix_bind.ux.gid;
3089 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003090
3091 /* NOTE: the following line might create several listeners if there
3092 * are comma-separated IPs or port ranges. So all further processing
3093 * will have to be applied to all listeners created after last_listen.
3094 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003095 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3096 if (errmsg && *errmsg) {
3097 indent_msg(&errmsg, 2);
3098 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003099 }
3100 else
3101 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3102 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003106
Willy Tarreau4348fad2012-09-20 16:48:07 +02003107 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3108 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003109 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003110 }
3111
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003112 cur_arg = 2;
3113 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003114 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003115 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003116 char *err;
3117
Willy Tarreau26982662012-09-12 23:17:10 +02003118 kw = bind_find_kw(args[cur_arg]);
3119 if (kw) {
3120 char *err = NULL;
3121 int code;
3122
3123 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003124 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3125 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003126 cur_arg += 1 + kw->skip ;
3127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130
Willy Tarreau4348fad2012-09-20 16:48:07 +02003131 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003132 err_code |= code;
3133
3134 if (code) {
3135 if (err && *err) {
3136 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003137 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003138 }
3139 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003140 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3141 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003142 if (code & ERR_FATAL) {
3143 free(err);
3144 cur_arg += 1 + kw->skip;
3145 goto out;
3146 }
3147 }
3148 free(err);
3149 cur_arg += 1 + kw->skip;
3150 continue;
3151 }
3152
Willy Tarreau8638f482012-09-18 18:01:17 +02003153 err = NULL;
3154 if (!bind_dumped) {
3155 bind_dump_kws(&err);
3156 indent_msg(&err, 4);
3157 bind_dumped = 1;
3158 }
3159
3160 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3161 file, linenum, args[0], args[1], args[cur_arg],
3162 err ? " Registered keywords :" : "", err ? err : "");
3163 free(err);
3164
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003167 }
Willy Tarreau93893792009-07-23 13:19:11 +02003168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 }
3170 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003171 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3173 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003177 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003179
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 /* flush useless bits */
3181 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003184 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003185 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003187
William Lallemanddf1425a2015-04-28 20:17:49 +02003188 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3189 goto out;
3190
Willy Tarreau1c47f852006-07-09 08:22:27 +02003191 if (!*args[1]) {
3192 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003196 }
3197
Willy Tarreaua534fea2008-08-03 12:19:50 +02003198 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003199 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003200 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003201 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003202 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3203
Willy Tarreau93893792009-07-23 13:19:11 +02003204 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003207 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3208 goto out;
3209
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3211 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3212 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3213 else {
3214 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
3218 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003219 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003220 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003221
3222 if (curproxy == &defproxy) {
3223 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3224 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003227 }
3228
William Lallemanddf1425a2015-04-28 20:17:49 +02003229 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3230 goto out;
3231
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003232 if (!*args[1]) {
3233 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003237 }
3238
3239 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003240 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003241 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003242
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003243 if (curproxy->uuid <= 0) {
3244 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003245 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003248 }
3249
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003250 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3251 if (node) {
3252 struct proxy *target = container_of(node, struct proxy, conf.id);
3253 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3254 file, linenum, proxy_type_str(curproxy), curproxy->id,
3255 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
3258 }
3259 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003260 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003261 else if (!strcmp(args[0], "description")) {
3262 int i, len=0;
3263 char *d;
3264
Cyril Bonté99ed3272010-01-24 23:29:44 +01003265 if (curproxy == &defproxy) {
3266 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3267 file, linenum, args[0]);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003272 if (!*args[1]) {
3273 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3274 file, linenum, args[0]);
3275 return -1;
3276 }
3277
Willy Tarreau348acfe2014-04-14 15:00:39 +02003278 for (i = 1; *args[i]; i++)
3279 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003280
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003281 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003282 curproxy->desc = d;
3283
Willy Tarreau348acfe2014-04-14 15:00:39 +02003284 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3285 for (i = 2; *args[i]; i++)
3286 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003287
3288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003290 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 curproxy->state = PR_STSTOPPED;
3293 }
3294 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003295 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 curproxy->state = PR_STNEW;
3298 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003299 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3300 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003301 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003302
3303 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003304 unsigned int low, high;
3305
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003306 if (strcmp(args[cur_arg], "all") == 0) {
3307 set = 0;
3308 break;
3309 }
3310 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003311 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003312 }
3313 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003314 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003315 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003316 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003317 char *dash = strchr(args[cur_arg], '-');
3318
3319 low = high = str2uic(args[cur_arg]);
3320 if (dash)
3321 high = str2uic(dash + 1);
3322
3323 if (high < low) {
3324 unsigned int swap = low;
3325 low = high;
3326 high = swap;
3327 }
3328
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003329 if (low < 1 || high > LONGBITS) {
3330 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3331 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003334 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003335 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003336 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003337 }
3338 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003339 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3340 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003343 }
3344 cur_arg++;
3345 }
3346 curproxy->bind_proc = set;
3347 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003348 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003349 if (curproxy == &defproxy) {
3350 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003353 }
3354
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003355 err = invalid_char(args[1]);
3356 if (err) {
3357 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3358 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003360 }
3361
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003362 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003363 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3364 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003367 }
3368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3370 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371
Willy Tarreau977b8e42006-12-29 14:19:17 +01003372 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003373 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003374
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 if (*(args[1]) == 0) {
3376 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3377 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003381
Willy Tarreau67402132012-05-31 20:40:20 +02003382 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003383 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003384 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003385 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 curproxy->cookie_name = strdup(args[1]);
3387 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003388
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 cur_arg = 2;
3390 while (*(args[cur_arg])) {
3391 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003392 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003395 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 }
3397 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003398 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003401 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003404 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003406 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003407 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003410 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003412 else if (!strcmp(args[cur_arg], "httponly")) {
3413 curproxy->ck_opts |= PR_CK_HTTPONLY;
3414 }
3415 else if (!strcmp(args[cur_arg], "secure")) {
3416 curproxy->ck_opts |= PR_CK_SECURE;
3417 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003418 else if (!strcmp(args[cur_arg], "domain")) {
3419 if (!*args[cur_arg + 1]) {
3420 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3421 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003424 }
3425
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003426 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003427 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003428 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3429 " dots nor does not start with a dot."
3430 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003431 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003432 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003433 }
3434
3435 err = invalid_domainchar(args[cur_arg + 1]);
3436 if (err) {
3437 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3438 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003441 }
3442
Willy Tarreau68a897b2009-12-03 23:28:34 +01003443 if (!curproxy->cookie_domain) {
3444 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3445 } else {
3446 /* one domain was already specified, add another one by
3447 * building the string which will be returned along with
3448 * the cookie.
3449 */
3450 char *new_ptr;
3451 int new_len = strlen(curproxy->cookie_domain) +
3452 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3453 new_ptr = malloc(new_len);
3454 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3455 free(curproxy->cookie_domain);
3456 curproxy->cookie_domain = new_ptr;
3457 }
Willy Tarreau31936852010-10-06 16:59:56 +02003458 cur_arg++;
3459 }
3460 else if (!strcmp(args[cur_arg], "maxidle")) {
3461 unsigned int maxidle;
3462 const char *res;
3463
3464 if (!*args[cur_arg + 1]) {
3465 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3466 file, linenum, args[cur_arg]);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
3470
3471 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3472 if (res) {
3473 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3474 file, linenum, *res, args[cur_arg]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
3478 curproxy->cookie_maxidle = maxidle;
3479 cur_arg++;
3480 }
3481 else if (!strcmp(args[cur_arg], "maxlife")) {
3482 unsigned int maxlife;
3483 const char *res;
3484
3485 if (!*args[cur_arg + 1]) {
3486 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3487 file, linenum, args[cur_arg]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491
3492 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3493 if (res) {
3494 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3495 file, linenum, *res, args[cur_arg]);
3496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
3498 }
3499 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003500 cur_arg++;
3501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003503 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 +02003504 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 }
3508 cur_arg++;
3509 }
Willy Tarreau67402132012-05-31 20:40:20 +02003510 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3512 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 }
3515
Willy Tarreau67402132012-05-31 20:40:20 +02003516 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3518 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003521
Willy Tarreau67402132012-05-31 20:40:20 +02003522 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003523 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3524 file, linenum);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003528 else if (!strcmp(args[0], "email-alert")) {
3529 if (*(args[1]) == 0) {
3530 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3531 file, linenum, args[0]);
3532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
3534 }
3535
3536 if (!strcmp(args[1], "from")) {
3537 if (*(args[1]) == 0) {
3538 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3539 file, linenum, args[1]);
3540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
3542 }
3543 free(curproxy->email_alert.from);
3544 curproxy->email_alert.from = strdup(args[2]);
3545 }
3546 else if (!strcmp(args[1], "mailers")) {
3547 if (*(args[1]) == 0) {
3548 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3549 file, linenum, args[1]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
3553 free(curproxy->email_alert.mailers.name);
3554 curproxy->email_alert.mailers.name = strdup(args[2]);
3555 }
3556 else if (!strcmp(args[1], "myhostname")) {
3557 if (*(args[1]) == 0) {
3558 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3559 file, linenum, args[1]);
3560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
3562 }
3563 free(curproxy->email_alert.myhostname);
3564 curproxy->email_alert.myhostname = strdup(args[2]);
3565 }
Simon Horman64e34162015-02-06 11:11:57 +09003566 else if (!strcmp(args[1], "level")) {
3567 curproxy->email_alert.level = get_log_level(args[2]);
3568 if (curproxy->email_alert.level < 0) {
3569 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3570 file, linenum, args[1], args[2]);
3571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
3573 }
3574 }
Simon Horman9dc49962015-01-30 11:22:59 +09003575 else if (!strcmp(args[1], "to")) {
3576 if (*(args[1]) == 0) {
3577 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3578 file, linenum, args[1]);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
3581 }
3582 free(curproxy->email_alert.to);
3583 curproxy->email_alert.to = strdup(args[2]);
3584 }
3585 else {
3586 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3587 file, linenum, args[1]);
3588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
3590 }
Simon Horman64e34162015-02-06 11:11:57 +09003591 /* Indicate that the email_alert is at least partially configured */
3592 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003593 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003594 else if (!strcmp(args[0], "external-check")) {
3595 if (*(args[1]) == 0) {
3596 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3597 file, linenum, args[0]);
3598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
3600 }
3601
3602 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003603 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003604 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003605 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003606 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3607 file, linenum, args[1]);
3608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
3610 }
3611 free(curproxy->check_command);
3612 curproxy->check_command = strdup(args[2]);
3613 }
3614 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003615 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003616 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003617 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003618 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3619 file, linenum, args[1]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623 free(curproxy->check_path);
3624 curproxy->check_path = strdup(args[2]);
3625 }
3626 else {
3627 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3628 file, linenum, args[1]);
3629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
3631 }
3632 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003633 else if (!strcmp(args[0], "persist")) { /* persist */
3634 if (*(args[1]) == 0) {
3635 Alert("parsing [%s:%d] : missing persist method.\n",
3636 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003639 }
3640
3641 if (!strncmp(args[1], "rdp-cookie", 10)) {
3642 curproxy->options2 |= PR_O2_RDPC_PRST;
3643
Emeric Brunb982a3d2010-01-04 15:45:53 +01003644 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003645 const char *beg, *end;
3646
3647 beg = args[1] + 11;
3648 end = strchr(beg, ')');
3649
William Lallemanddf1425a2015-04-28 20:17:49 +02003650 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3651 goto out;
3652
Emeric Brun647caf12009-06-30 17:57:00 +02003653 if (!end || end == beg) {
3654 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3655 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003658 }
3659
3660 free(curproxy->rdp_cookie_name);
3661 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3662 curproxy->rdp_cookie_len = end-beg;
3663 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003664 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003665 free(curproxy->rdp_cookie_name);
3666 curproxy->rdp_cookie_name = strdup("msts");
3667 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3668 }
3669 else { /* syntax */
3670 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3671 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003674 }
3675 }
3676 else {
3677 Alert("parsing [%s:%d] : unknown persist method.\n",
3678 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003681 }
3682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003684 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
3687 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003688 else if (!strcmp(args[0], "load-server-state-from-file")) {
3689 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3690 err_code |= ERR_WARN;
3691 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3692 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3693 }
3694 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3695 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3696 }
3697 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3698 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3699 }
3700 else {
3701 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3702 file, linenum, args[0], args[1]);
3703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
3705 }
3706 }
3707 else if (!strcmp(args[0], "server-state-file-name")) {
3708 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3709 err_code |= ERR_WARN;
3710 if (*(args[1]) == 0) {
3711 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3712 file, linenum, args[0]);
3713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
3715 }
3716 else if (!strcmp(args[1], "use-backend-name"))
3717 curproxy->server_state_file_name = strdup(curproxy->id);
3718 else
3719 curproxy->server_state_file_name = strdup(args[1]);
3720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003722 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003723 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003724
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003726 if (curproxy == &defproxy) {
3727 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
3730 }
3731
William Lallemand1a748ae2015-05-19 16:37:23 +02003732 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3733 goto out;
3734
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 if (*(args[4]) == 0) {
3736 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003741 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 curproxy->capture_name = strdup(args[2]);
3743 curproxy->capture_namelen = strlen(curproxy->capture_name);
3744 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 curproxy->to_log |= LW_COOKIE;
3746 }
3747 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3748 struct cap_hdr *hdr;
3749
3750 if (curproxy == &defproxy) {
3751 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 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 }
3755
William Lallemand1a748ae2015-05-19 16:37:23 +02003756 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3757 goto out;
3758
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3760 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3761 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 }
3765
Vincent Bernat02779b62016-04-03 13:48:43 +02003766 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 hdr->next = curproxy->req_cap;
3768 hdr->name = strdup(args[3]);
3769 hdr->namelen = strlen(args[3]);
3770 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003771 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 hdr->index = curproxy->nb_req_cap++;
3773 curproxy->req_cap = hdr;
3774 curproxy->to_log |= LW_REQHDR;
3775 }
3776 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3777 struct cap_hdr *hdr;
3778
3779 if (curproxy == &defproxy) {
3780 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 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 }
3784
William Lallemand1a748ae2015-05-19 16:37:23 +02003785 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3786 goto out;
3787
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3789 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3790 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003794 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 hdr->next = curproxy->rsp_cap;
3796 hdr->name = strdup(args[3]);
3797 hdr->namelen = strlen(args[3]);
3798 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003799 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 hdr->index = curproxy->nb_rsp_cap++;
3801 curproxy->rsp_cap = hdr;
3802 curproxy->to_log |= LW_RSPHDR;
3803 }
3804 else {
3805 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3806 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003812 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003814
William Lallemanddf1425a2015-04-28 20:17:49 +02003815 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3816 goto out;
3817
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 if (*(args[1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3820 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
3824 curproxy->conn_retries = atol(args[1]);
3825 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003826 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003827 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003828
3829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
3833 }
3834
Willy Tarreau20b0de52012-12-24 15:45:22 +01003835 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003836 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003837 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3838 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3839 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3840 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003841 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 +01003842 file, linenum, args[0]);
3843 err_code |= ERR_WARN;
3844 }
3845
Willy Tarreauff011f22011-01-06 17:51:27 +01003846 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003847
Willy Tarreauff011f22011-01-06 17:51:27 +01003848 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003849 err_code |= ERR_ALERT | ERR_ABORT;
3850 goto out;
3851 }
3852
Willy Tarreau5002f572014-04-23 01:32:02 +02003853 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003854 err_code |= warnif_cond_conflicts(rule->cond,
3855 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3856 file, linenum);
3857
Willy Tarreauff011f22011-01-06 17:51:27 +01003858 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003859 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003860 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003861 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003862
3863 if (curproxy == &defproxy) {
3864 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
3867 }
3868
3869 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003870 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003871 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3872 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003873 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3874 file, linenum, args[0]);
3875 err_code |= ERR_WARN;
3876 }
3877
3878 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3879
3880 if (!rule) {
3881 err_code |= ERR_ALERT | ERR_ABORT;
3882 goto out;
3883 }
3884
3885 err_code |= warnif_cond_conflicts(rule->cond,
3886 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3887 file, linenum);
3888
3889 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3890 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003891 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3892 /* set the header name and length into the proxy structure */
3893 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3894 err_code |= ERR_WARN;
3895
3896 if (!*args[1]) {
3897 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3898 file, linenum, args[0]);
3899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
3901 }
3902
3903 /* set the desired header name */
3904 free(curproxy->server_id_hdr_name);
3905 curproxy->server_id_hdr_name = strdup(args[1]);
3906 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3907 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003908 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003909 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003910
Willy Tarreaub099aca2008-10-12 17:26:37 +02003911 if (curproxy == &defproxy) {
3912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003915 }
3916
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003917 /* emulate "block" using "http-request block". Since these rules are supposed to
3918 * be processed before all http-request rules, we put them into their own list
3919 * and will insert them at the end.
3920 */
3921 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3922 if (!rule) {
3923 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003924 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003925 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003926 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3927 err_code |= warnif_cond_conflicts(rule->cond,
3928 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3929 file, linenum);
3930 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003931
3932 if (!already_warned(WARN_BLOCK_DEPRECATED))
3933 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]);
3934
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003935 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003936 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003937 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003938
Cyril Bonté99ed3272010-01-24 23:29:44 +01003939 if (curproxy == &defproxy) {
3940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
3943 }
3944
Willy Tarreaube4653b2015-05-28 15:26:58 +02003945 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003946 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3947 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003950 }
3951
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003952 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003953 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003954 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);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003957 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003958 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003959 struct switching_rule *rule;
3960
Willy Tarreaub099aca2008-10-12 17:26:37 +02003961 if (curproxy == &defproxy) {
3962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003965 }
3966
Willy Tarreau55ea7572007-06-17 19:56:27 +02003967 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003968 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003969
3970 if (*(args[1]) == 0) {
3971 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003974 }
3975
Willy Tarreauf51658d2014-04-23 01:21:56 +02003976 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3977 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3978 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3979 file, linenum, errmsg);
3980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
3982 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003983
Willy Tarreauf51658d2014-04-23 01:21:56 +02003984 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003985 }
3986
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003987 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003988 if (!rule) {
3989 Alert("Out of memory error.\n");
3990 goto out;
3991 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003992 rule->cond = cond;
3993 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003994 rule->line = linenum;
3995 rule->file = strdup(file);
3996 if (!rule->file) {
3997 Alert("Out of memory error.\n");
3998 goto out;
3999 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004000 LIST_INIT(&rule->list);
4001 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4002 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004003 else if (strcmp(args[0], "use-server") == 0) {
4004 struct server_rule *rule;
4005
4006 if (curproxy == &defproxy) {
4007 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
4011
4012 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4013 err_code |= ERR_WARN;
4014
4015 if (*(args[1]) == 0) {
4016 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
4021 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4022 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4023 file, linenum, args[0]);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004028 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4029 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4030 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
4033 }
4034
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004035 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004036
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004037 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004038 rule->cond = cond;
4039 rule->srv.name = strdup(args[1]);
4040 LIST_INIT(&rule->list);
4041 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4042 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4043 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004044 else if ((!strcmp(args[0], "force-persist")) ||
4045 (!strcmp(args[0], "ignore-persist"))) {
4046 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004047
4048 if (curproxy == &defproxy) {
4049 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053
4054 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4055 err_code |= ERR_WARN;
4056
Willy Tarreauef6494c2010-01-28 17:12:36 +01004057 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004058 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4059 file, linenum, args[0]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004064 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4065 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4066 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004071 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4072 * where force-persist is applied.
4073 */
4074 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004075
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004076 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004077 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004078 if (!strcmp(args[0], "force-persist")) {
4079 rule->type = PERSIST_TYPE_FORCE;
4080 } else {
4081 rule->type = PERSIST_TYPE_IGNORE;
4082 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004083 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004084 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004085 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004086 else if (!strcmp(args[0], "stick-table")) {
4087 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004088 struct proxy *other;
4089
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004090 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004091 if (other) {
4092 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4093 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004097
Emeric Brun32da3c42010-09-23 18:39:19 +02004098 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099 curproxy->table.type = (unsigned int)-1;
4100 while (*args[myidx]) {
4101 const char *err;
4102
4103 if (strcmp(args[myidx], "size") == 0) {
4104 myidx++;
4105 if (!*(args[myidx])) {
4106 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4107 file, linenum, args[myidx-1]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
4111 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4112 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4113 file, linenum, *err, args[myidx-1]);
4114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
4116 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004117 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004118 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004119 else if (strcmp(args[myidx], "peers") == 0) {
4120 myidx++;
Godbach50523162013-12-11 19:48:57 +08004121 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004122 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4123 file, linenum, args[myidx-1]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Godbach50523162013-12-11 19:48:57 +08004126 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004127 curproxy->table.peers.name = strdup(args[myidx++]);
4128 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004129 else if (strcmp(args[myidx], "expire") == 0) {
4130 myidx++;
4131 if (!*(args[myidx])) {
4132 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4133 file, linenum, args[myidx-1]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4138 if (err) {
4139 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4140 file, linenum, *err, args[myidx-1]);
4141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
4143 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004144 if (val > INT_MAX) {
4145 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4146 file, linenum, val);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004151 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 }
4153 else if (strcmp(args[myidx], "nopurge") == 0) {
4154 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004155 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 }
4157 else if (strcmp(args[myidx], "type") == 0) {
4158 myidx++;
4159 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4160 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4161 file, linenum, args[myidx]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004165 /* myidx already points to next arg */
4166 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004167 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004168 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004169 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004170
4171 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004172 nw = args[myidx];
4173 while (*nw) {
4174 /* the "store" keyword supports a comma-separated list */
4175 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004176 sa = NULL; /* store arg */
4177 while (*nw && *nw != ',') {
4178 if (*nw == '(') {
4179 *nw = 0;
4180 sa = ++nw;
4181 while (*nw != ')') {
4182 if (!*nw) {
4183 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4184 file, linenum, args[0], cw);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188 nw++;
4189 }
4190 *nw = '\0';
4191 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004192 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004193 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004194 if (*nw)
4195 *nw++ = '\0';
4196 type = stktable_get_data_type(cw);
4197 if (type < 0) {
4198 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4199 file, linenum, args[0], cw);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
Willy Tarreauac782882010-06-20 10:41:54 +02004203
4204 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4205 switch (err) {
4206 case PE_NONE: break;
4207 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004208 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4209 file, linenum, args[0], cw);
4210 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004211 break;
4212
4213 case PE_ARG_MISSING:
4214 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4215 file, linenum, args[0], cw);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218
4219 case PE_ARG_NOT_USED:
4220 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4221 file, linenum, args[0], cw);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224
4225 default:
4226 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4227 file, linenum, args[0], cw);
4228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004230 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004231 }
4232 myidx++;
4233 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004234 else {
4235 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4236 file, linenum, args[myidx]);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004239 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004240 }
4241
4242 if (!curproxy->table.size) {
4243 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4244 file, linenum);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
4248
4249 if (curproxy->table.type == (unsigned int)-1) {
4250 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4251 file, linenum);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255 }
4256 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004257 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004258 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004259 int myidx = 0;
4260 const char *name = NULL;
4261 int flags;
4262
4263 if (curproxy == &defproxy) {
4264 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
4268
4269 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4270 err_code |= ERR_WARN;
4271 goto out;
4272 }
4273
4274 myidx++;
4275 if ((strcmp(args[myidx], "store") == 0) ||
4276 (strcmp(args[myidx], "store-request") == 0)) {
4277 myidx++;
4278 flags = STK_IS_STORE;
4279 }
4280 else if (strcmp(args[myidx], "store-response") == 0) {
4281 myidx++;
4282 flags = STK_IS_STORE | STK_ON_RSP;
4283 }
4284 else if (strcmp(args[myidx], "match") == 0) {
4285 myidx++;
4286 flags = STK_IS_MATCH;
4287 }
4288 else if (strcmp(args[myidx], "on") == 0) {
4289 myidx++;
4290 flags = STK_IS_MATCH | STK_IS_STORE;
4291 }
4292 else {
4293 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297
4298 if (*(args[myidx]) == 0) {
4299 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
4302 }
4303
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004304 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004305 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004306 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004307 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311
4312 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004313 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4314 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4315 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004316 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004317 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004318 goto out;
4319 }
4320 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004321 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4322 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4323 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004324 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004325 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004326 goto out;
4327 }
4328 }
4329
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004330 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004331 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004332
Emeric Brunb982a3d2010-01-04 15:45:53 +01004333 if (strcmp(args[myidx], "table") == 0) {
4334 myidx++;
4335 name = args[myidx++];
4336 }
4337
Willy Tarreauef6494c2010-01-28 17:12:36 +01004338 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004339 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4340 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4341 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004342 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004343 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004344 goto out;
4345 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004346 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004347 else if (*(args[myidx])) {
4348 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4349 file, linenum, args[0], args[myidx]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004351 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004352 goto out;
4353 }
Emeric Brun97679e72010-09-23 17:56:44 +02004354 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004355 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004356 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004357 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004358
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004359 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004360 rule->cond = cond;
4361 rule->expr = expr;
4362 rule->flags = flags;
4363 rule->table.name = name ? strdup(name) : NULL;
4364 LIST_INIT(&rule->list);
4365 if (flags & STK_ON_RSP)
4366 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4367 else
4368 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 else if (!strcmp(args[0], "stats")) {
4371 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4372 curproxy->uri_auth = NULL; /* we must detach from the default config */
4373
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004374 if (!*args[1]) {
4375 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004376 } else if (!strcmp(args[1], "admin")) {
4377 struct stats_admin_rule *rule;
4378
4379 if (curproxy == &defproxy) {
4380 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
4383 }
4384
4385 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4386 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4387 err_code |= ERR_ALERT | ERR_ABORT;
4388 goto out;
4389 }
4390
4391 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4392 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4393 file, linenum, args[0], args[1]);
4394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
4396 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004397 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4398 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4399 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
4402 }
4403
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004404 err_code |= warnif_cond_conflicts(cond,
4405 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4406 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004407
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004408 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004409 rule->cond = cond;
4410 LIST_INIT(&rule->list);
4411 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 } else if (!strcmp(args[1], "uri")) {
4413 if (*(args[2]) == 0) {
4414 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4418 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004419 err_code |= ERR_ALERT | ERR_ABORT;
4420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 }
4422 } else if (!strcmp(args[1], "realm")) {
4423 if (*(args[2]) == 0) {
4424 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4428 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_ABORT;
4430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004432 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004433 unsigned interval;
4434
4435 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4436 if (err) {
4437 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4438 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004441 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_ABORT;
4444 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004445 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004446 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004447 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004448
4449 if (curproxy == &defproxy) {
4450 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
4453 }
4454
4455 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4456 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4457 err_code |= ERR_ALERT | ERR_ABORT;
4458 goto out;
4459 }
4460
Willy Tarreauff011f22011-01-06 17:51:27 +01004461 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004462 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004463 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4464 file, linenum, args[0]);
4465 err_code |= ERR_WARN;
4466 }
4467
Willy Tarreauff011f22011-01-06 17:51:27 +01004468 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004469
Willy Tarreauff011f22011-01-06 17:51:27 +01004470 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004471 err_code |= ERR_ALERT | ERR_ABORT;
4472 goto out;
4473 }
4474
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004475 err_code |= warnif_cond_conflicts(rule->cond,
4476 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4477 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004478 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004479
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 } else if (!strcmp(args[1], "auth")) {
4481 if (*(args[2]) == 0) {
4482 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4486 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_ABORT;
4488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
4490 } else if (!strcmp(args[1], "scope")) {
4491 if (*(args[2]) == 0) {
4492 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4496 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004497 err_code |= ERR_ALERT | ERR_ABORT;
4498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 }
4500 } else if (!strcmp(args[1], "enable")) {
4501 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4502 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_ABORT;
4504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004506 } else if (!strcmp(args[1], "hide-version")) {
4507 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4508 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004509 err_code |= ERR_ALERT | ERR_ABORT;
4510 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004511 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004512 } else if (!strcmp(args[1], "show-legends")) {
4513 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4514 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4515 err_code |= ERR_ALERT | ERR_ABORT;
4516 goto out;
4517 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004518 } else if (!strcmp(args[1], "show-node")) {
4519
4520 if (*args[2]) {
4521 int i;
4522 char c;
4523
4524 for (i=0; args[2][i]; i++) {
4525 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004526 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4527 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004528 break;
4529 }
4530
4531 if (!i || args[2][i]) {
4532 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4533 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4534 file, linenum, args[0], args[1]);
4535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
4538 }
4539
4540 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4541 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4542 err_code |= ERR_ALERT | ERR_ABORT;
4543 goto out;
4544 }
4545 } else if (!strcmp(args[1], "show-desc")) {
4546 char *desc = NULL;
4547
4548 if (*args[2]) {
4549 int i, len=0;
4550 char *d;
4551
Willy Tarreau348acfe2014-04-14 15:00:39 +02004552 for (i = 2; *args[i]; i++)
4553 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004554
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004555 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004556
Willy Tarreau348acfe2014-04-14 15:00:39 +02004557 d += snprintf(d, desc + len - d, "%s", args[2]);
4558 for (i = 3; *args[i]; i++)
4559 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004560 }
4561
4562 if (!*args[2] && !global.desc)
4563 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4564 file, linenum, args[1]);
4565 else {
4566 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4567 free(desc);
4568 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4569 err_code |= ERR_ALERT | ERR_ABORT;
4570 goto out;
4571 }
4572 free(desc);
4573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004575stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004576 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 +01004577 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 }
4581 }
4582 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004583 int optnum;
4584
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004585 if (*(args[1]) == '\0') {
4586 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4587 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004591
4592 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4593 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004594 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4595 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4596 file, linenum, cfg_opts[optnum].name);
4597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004600 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4601 goto out;
4602
Willy Tarreau93893792009-07-23 13:19:11 +02004603 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4604 err_code |= ERR_WARN;
4605 goto out;
4606 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004607
Willy Tarreau3842f002009-06-14 11:39:52 +02004608 curproxy->no_options &= ~cfg_opts[optnum].val;
4609 curproxy->options &= ~cfg_opts[optnum].val;
4610
4611 switch (kwm) {
4612 case KWM_STD:
4613 curproxy->options |= cfg_opts[optnum].val;
4614 break;
4615 case KWM_NO:
4616 curproxy->no_options |= cfg_opts[optnum].val;
4617 break;
4618 case KWM_DEF: /* already cleared */
4619 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004620 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004621
Willy Tarreau93893792009-07-23 13:19:11 +02004622 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004623 }
4624 }
4625
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004626 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4627 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004628 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4629 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4630 file, linenum, cfg_opts2[optnum].name);
4631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
4633 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004634 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4635 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004636 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4637 err_code |= ERR_WARN;
4638 goto out;
4639 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004640
Willy Tarreau3842f002009-06-14 11:39:52 +02004641 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4642 curproxy->options2 &= ~cfg_opts2[optnum].val;
4643
4644 switch (kwm) {
4645 case KWM_STD:
4646 curproxy->options2 |= cfg_opts2[optnum].val;
4647 break;
4648 case KWM_NO:
4649 curproxy->no_options2 |= cfg_opts2[optnum].val;
4650 break;
4651 case KWM_DEF: /* already cleared */
4652 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004653 }
Willy Tarreau93893792009-07-23 13:19:11 +02004654 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004655 }
4656 }
4657
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004658 /* HTTP options override each other. They can be cancelled using
4659 * "no option xxx" which only switches to default mode if the mode
4660 * was this one (useful for cancelling options set in defaults
4661 * sections).
4662 */
4663 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004664 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4665 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004666 if (kwm == KWM_STD) {
4667 curproxy->options &= ~PR_O_HTTP_MODE;
4668 curproxy->options |= PR_O_HTTP_PCL;
4669 goto out;
4670 }
4671 else if (kwm == KWM_NO) {
4672 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4673 curproxy->options &= ~PR_O_HTTP_MODE;
4674 goto out;
4675 }
4676 }
4677 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004678 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4679 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004680 if (kwm == KWM_STD) {
4681 curproxy->options &= ~PR_O_HTTP_MODE;
4682 curproxy->options |= PR_O_HTTP_FCL;
4683 goto out;
4684 }
4685 else if (kwm == KWM_NO) {
4686 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4687 curproxy->options &= ~PR_O_HTTP_MODE;
4688 goto out;
4689 }
4690 }
4691 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004692 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4693 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004694 if (kwm == KWM_STD) {
4695 curproxy->options &= ~PR_O_HTTP_MODE;
4696 curproxy->options |= PR_O_HTTP_SCL;
4697 goto out;
4698 }
4699 else if (kwm == KWM_NO) {
4700 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4701 curproxy->options &= ~PR_O_HTTP_MODE;
4702 goto out;
4703 }
4704 }
4705 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004706 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4707 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004708 if (kwm == KWM_STD) {
4709 curproxy->options &= ~PR_O_HTTP_MODE;
4710 curproxy->options |= PR_O_HTTP_KAL;
4711 goto out;
4712 }
4713 else if (kwm == KWM_NO) {
4714 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4715 curproxy->options &= ~PR_O_HTTP_MODE;
4716 goto out;
4717 }
4718 }
4719 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004720 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4721 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004722 if (kwm == KWM_STD) {
4723 curproxy->options &= ~PR_O_HTTP_MODE;
4724 curproxy->options |= PR_O_HTTP_TUN;
4725 goto out;
4726 }
4727 else if (kwm == KWM_NO) {
4728 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4729 curproxy->options &= ~PR_O_HTTP_MODE;
4730 goto out;
4731 }
4732 }
4733
Joseph Lynch726ab712015-05-11 23:25:34 -07004734 /* Redispatch can take an integer argument that control when the
4735 * resispatch occurs. All values are relative to the retries option.
4736 * This can be cancelled using "no option xxx".
4737 */
4738 if (strcmp(args[1], "redispatch") == 0) {
4739 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4740 err_code |= ERR_WARN;
4741 goto out;
4742 }
4743
4744 curproxy->no_options &= ~PR_O_REDISP;
4745 curproxy->options &= ~PR_O_REDISP;
4746
4747 switch (kwm) {
4748 case KWM_STD:
4749 curproxy->options |= PR_O_REDISP;
4750 curproxy->redispatch_after = -1;
4751 if(*args[2]) {
4752 curproxy->redispatch_after = atol(args[2]);
4753 }
4754 break;
4755 case KWM_NO:
4756 curproxy->no_options |= PR_O_REDISP;
4757 curproxy->redispatch_after = 0;
4758 break;
4759 case KWM_DEF: /* already cleared */
4760 break;
4761 }
4762 goto out;
4763 }
4764
Willy Tarreau3842f002009-06-14 11:39:52 +02004765 if (kwm != KWM_STD) {
4766 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004767 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004768 err_code |= ERR_ALERT | ERR_FATAL;
4769 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004770 }
4771
Emeric Brun3a058f32009-06-30 18:26:00 +02004772 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004773 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004775 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004776 if (*(args[2]) != '\0') {
4777 if (!strcmp(args[2], "clf")) {
4778 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004779 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004780 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004781 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004784 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004785 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4786 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004787 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004788 if (curproxy->conf.logformat_string != default_http_log_format &&
4789 curproxy->conf.logformat_string != default_tcp_log_format &&
4790 curproxy->conf.logformat_string != clf_http_log_format)
4791 free(curproxy->conf.logformat_string);
4792 curproxy->conf.logformat_string = logformat;
4793
4794 free(curproxy->conf.lfs_file);
4795 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4796 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004797 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004798 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004800 if (curproxy->conf.logformat_string != default_http_log_format &&
4801 curproxy->conf.logformat_string != default_tcp_log_format &&
4802 curproxy->conf.logformat_string != clf_http_log_format)
4803 free(curproxy->conf.logformat_string);
4804 curproxy->conf.logformat_string = default_tcp_log_format;
4805
4806 free(curproxy->conf.lfs_file);
4807 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4808 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004809
4810 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4811 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004814 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004815 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004816 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004817
William Lallemanddf1425a2015-04-28 20:17:49 +02004818 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4819 goto out;
4820
Willy Tarreau13943ab2006-12-31 00:24:10 +01004821 if (curproxy->cap & PR_CAP_FE)
4822 curproxy->options |= PR_O_TCP_CLI_KA;
4823 if (curproxy->cap & PR_CAP_BE)
4824 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 }
4826 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004828 err_code |= ERR_WARN;
4829
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004831 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004832 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004833 curproxy->options2 &= ~PR_O2_CHK_ANY;
4834 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 if (!*args[2]) { /* no argument */
4836 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4837 curproxy->check_len = strlen(DEF_CHECK_REQ);
4838 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004839 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004840 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004842 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004844 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 if (*args[4])
4846 reqlen += strlen(args[4]);
4847 else
4848 reqlen += strlen("HTTP/1.0");
4849
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004850 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004852 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004854 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4855 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004856 }
4857 else if (!strcmp(args[1], "ssl-hello-chk")) {
4858 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004861
Willy Tarreaua534fea2008-08-03 12:19:50 +02004862 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004863 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004864 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004865 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004866
4867 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
Willy Tarreau23677902007-05-08 23:50:35 +02004870 else if (!strcmp(args[1], "smtpchk")) {
4871 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004872 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004873 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004874 curproxy->options2 &= ~PR_O2_CHK_ANY;
4875 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004876
4877 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4878 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4879 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4880 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4881 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4882 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004883 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004884 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4885 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4886 } else {
4887 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4888 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4889 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4890 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4891 }
4892 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004893 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4894 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004895 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004896 else if (!strcmp(args[1], "pgsql-check")) {
4897 /* use PostgreSQL request to check servers' health */
4898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4899 err_code |= ERR_WARN;
4900
4901 free(curproxy->check_req);
4902 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004903 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004904 curproxy->options2 |= PR_O2_PGSQL_CHK;
4905
4906 if (*(args[2])) {
4907 int cur_arg = 2;
4908
4909 while (*(args[cur_arg])) {
4910 if (strcmp(args[cur_arg], "user") == 0) {
4911 char * packet;
4912 uint32_t packet_len;
4913 uint32_t pv;
4914
4915 /* suboption header - needs additional argument for it */
4916 if (*(args[cur_arg+1]) == 0) {
4917 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4918 file, linenum, args[0], args[1], args[cur_arg]);
4919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
4921 }
4922
4923 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4924 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4925 pv = htonl(0x30000); /* protocol version 3.0 */
4926
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004927 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004928
4929 memcpy(packet + 4, &pv, 4);
4930
4931 /* copy "user" */
4932 memcpy(packet + 8, "user", 4);
4933
4934 /* copy username */
4935 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4936
4937 free(curproxy->check_req);
4938 curproxy->check_req = packet;
4939 curproxy->check_len = packet_len;
4940
4941 packet_len = htonl(packet_len);
4942 memcpy(packet, &packet_len, 4);
4943 cur_arg += 2;
4944 } else {
4945 /* unknown suboption - catchall */
4946 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4947 file, linenum, args[0], args[1]);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
4951 } /* end while loop */
4952 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004953 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4954 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004955 }
4956
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004957 else if (!strcmp(args[1], "redis-check")) {
4958 /* use REDIS PING request to check servers' health */
4959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4960 err_code |= ERR_WARN;
4961
4962 free(curproxy->check_req);
4963 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004964 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004965 curproxy->options2 |= PR_O2_REDIS_CHK;
4966
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004967 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004968 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4969 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004970
4971 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4972 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004973 }
4974
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004975 else if (!strcmp(args[1], "mysql-check")) {
4976 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4978 err_code |= ERR_WARN;
4979
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004980 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004981 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004982 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004983 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004984
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004985 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004986 * const char mysql40_client_auth_pkt[] = {
4987 * "\x0e\x00\x00" // packet length
4988 * "\x01" // packet number
4989 * "\x00\x00" // client capabilities
4990 * "\x00\x00\x01" // max packet
4991 * "haproxy\x00" // username (null terminated string)
4992 * "\x00" // filler (always 0x00)
4993 * "\x01\x00\x00" // packet length
4994 * "\x00" // packet number
4995 * "\x01" // COM_QUIT command
4996 * };
4997 */
4998
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004999 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5000 * const char mysql41_client_auth_pkt[] = {
5001 * "\x0e\x00\x00\" // packet length
5002 * "\x01" // packet number
5003 * "\x00\x00\x00\x00" // client capabilities
5004 * "\x00\x00\x00\x01" // max packet
5005 * "\x21" // character set (UTF-8)
5006 * char[23] // All zeroes
5007 * "haproxy\x00" // username (null terminated string)
5008 * "\x00" // filler (always 0x00)
5009 * "\x01\x00\x00" // packet length
5010 * "\x00" // packet number
5011 * "\x01" // COM_QUIT command
5012 * };
5013 */
5014
5015
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005016 if (*(args[2])) {
5017 int cur_arg = 2;
5018
5019 while (*(args[cur_arg])) {
5020 if (strcmp(args[cur_arg], "user") == 0) {
5021 char *mysqluser;
5022 int packetlen, reqlen, userlen;
5023
5024 /* suboption header - needs additional argument for it */
5025 if (*(args[cur_arg+1]) == 0) {
5026 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5027 file, linenum, args[0], args[1], args[cur_arg]);
5028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
5030 }
5031 mysqluser = args[cur_arg + 1];
5032 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005033
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005034 if (*(args[cur_arg+2])) {
5035 if (!strcmp(args[cur_arg+2], "post-41")) {
5036 packetlen = userlen + 7 + 27;
5037 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005038
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005039 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005040 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005041 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005042
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005043 snprintf(curproxy->check_req, 4, "%c%c%c",
5044 ((unsigned char) packetlen & 0xff),
5045 ((unsigned char) (packetlen >> 8) & 0xff),
5046 ((unsigned char) (packetlen >> 16) & 0xff));
5047
5048 curproxy->check_req[3] = 1;
5049 curproxy->check_req[5] = 130;
5050 curproxy->check_req[11] = 1;
5051 curproxy->check_req[12] = 33;
5052 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5053 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5054 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5055 cur_arg += 3;
5056 } else {
5057 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
5060 }
5061 } else {
5062 packetlen = userlen + 7;
5063 reqlen = packetlen + 9;
5064
5065 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005066 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005067 curproxy->check_len = reqlen;
5068
5069 snprintf(curproxy->check_req, 4, "%c%c%c",
5070 ((unsigned char) packetlen & 0xff),
5071 ((unsigned char) (packetlen >> 8) & 0xff),
5072 ((unsigned char) (packetlen >> 16) & 0xff));
5073
5074 curproxy->check_req[3] = 1;
5075 curproxy->check_req[5] = 128;
5076 curproxy->check_req[8] = 1;
5077 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5078 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5079 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5080 cur_arg += 2;
5081 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005082 } else {
5083 /* unknown suboption - catchall */
5084 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5085 file, linenum, args[0], args[1]);
5086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
5088 }
5089 } /* end while loop */
5090 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005091 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005092 else if (!strcmp(args[1], "ldap-check")) {
5093 /* use LDAP request to check servers' health */
5094 free(curproxy->check_req);
5095 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005096 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005097 curproxy->options2 |= PR_O2_LDAP_CHK;
5098
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005099 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005100 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5101 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005102 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5103 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005104 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005105 else if (!strcmp(args[1], "spop-check")) {
5106 if (curproxy == &defproxy) {
5107 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5108 file, linenum, args[0], args[1]);
5109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
5111 }
5112 if (curproxy->cap & PR_CAP_FE) {
5113 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5114 file, linenum, args[0], args[1]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118
5119 /* use SPOE request to check servers' health */
5120 free(curproxy->check_req);
5121 curproxy->check_req = NULL;
5122 curproxy->options2 &= ~PR_O2_CHK_ANY;
5123 curproxy->options2 |= PR_O2_SPOP_CHK;
5124
5125 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
5126 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
5129 }
5130 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5131 goto out;
5132 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005133 else if (!strcmp(args[1], "tcp-check")) {
5134 /* use raw TCPCHK send/expect to check servers' health */
5135 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5136 err_code |= ERR_WARN;
5137
5138 free(curproxy->check_req);
5139 curproxy->check_req = NULL;
5140 curproxy->options2 &= ~PR_O2_CHK_ANY;
5141 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005142 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5143 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005144 }
Simon Horman98637e52014-06-20 12:30:16 +09005145 else if (!strcmp(args[1], "external-check")) {
5146 /* excute an external command to check servers' health */
5147 free(curproxy->check_req);
5148 curproxy->check_req = NULL;
5149 curproxy->options2 &= ~PR_O2_CHK_ANY;
5150 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005151 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5152 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005153 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005154 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005155 int cur_arg;
5156
5157 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5158 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005159 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005160
Willy Tarreau87cf5142011-08-19 22:57:24 +02005161 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005162
5163 free(curproxy->fwdfor_hdr_name);
5164 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5165 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5166
5167 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5168 cur_arg = 2;
5169 while (*(args[cur_arg])) {
5170 if (!strcmp(args[cur_arg], "except")) {
5171 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005172 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005173 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5174 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005177 }
5178 /* flush useless bits */
5179 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005180 cur_arg += 2;
5181 } else if (!strcmp(args[cur_arg], "header")) {
5182 /* suboption header - needs additional argument for it */
5183 if (*(args[cur_arg+1]) == 0) {
5184 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5185 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005188 }
5189 free(curproxy->fwdfor_hdr_name);
5190 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5191 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5192 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005193 } else if (!strcmp(args[cur_arg], "if-none")) {
5194 curproxy->options &= ~PR_O_FF_ALWAYS;
5195 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005196 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005197 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005198 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005199 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005202 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005203 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005204 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005205 else if (!strcmp(args[1], "originalto")) {
5206 int cur_arg;
5207
5208 /* insert x-original-to field, but not for the IP address listed as an except.
5209 * set default options (ie: bitfield, header name, etc)
5210 */
5211
5212 curproxy->options |= PR_O_ORGTO;
5213
5214 free(curproxy->orgto_hdr_name);
5215 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5216 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5217
Willy Tarreau87cf5142011-08-19 22:57:24 +02005218 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005219 cur_arg = 2;
5220 while (*(args[cur_arg])) {
5221 if (!strcmp(args[cur_arg], "except")) {
5222 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005223 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 +02005224 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5225 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005228 }
5229 /* flush useless bits */
5230 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5231 cur_arg += 2;
5232 } else if (!strcmp(args[cur_arg], "header")) {
5233 /* suboption header - needs additional argument for it */
5234 if (*(args[cur_arg+1]) == 0) {
5235 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5236 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005239 }
5240 free(curproxy->orgto_hdr_name);
5241 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5242 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5243 cur_arg += 2;
5244 } else {
5245 /* unknown suboption - catchall */
5246 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5247 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005250 }
5251 } /* end while loop */
5252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253 else {
5254 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
Willy Tarreau93893792009-07-23 13:19:11 +02005258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005260 else if (!strcmp(args[0], "default_backend")) {
5261 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005262 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005263
5264 if (*(args[1]) == 0) {
5265 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005266 err_code |= ERR_ALERT | ERR_FATAL;
5267 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005268 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005269 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005270 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005271
5272 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5273 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005276 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005278
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005279 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5280 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 +01005281 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005282 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 /* enable reconnections to dispatch */
5284 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005285
5286 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005289 else if (!strcmp(args[0], "http-reuse")) {
5290 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5291 err_code |= ERR_WARN;
5292
5293 if (strcmp(args[1], "never") == 0) {
5294 /* enable a graceful server shutdown on an HTTP 404 response */
5295 curproxy->options &= ~PR_O_REUSE_MASK;
5296 curproxy->options |= PR_O_REUSE_NEVR;
5297 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5298 goto out;
5299 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005300 else if (strcmp(args[1], "safe") == 0) {
5301 /* enable a graceful server shutdown on an HTTP 404 response */
5302 curproxy->options &= ~PR_O_REUSE_MASK;
5303 curproxy->options |= PR_O_REUSE_SAFE;
5304 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5305 goto out;
5306 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005307 else if (strcmp(args[1], "aggressive") == 0) {
5308 curproxy->options &= ~PR_O_REUSE_MASK;
5309 curproxy->options |= PR_O_REUSE_AGGR;
5310 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5311 goto out;
5312 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005313 else if (strcmp(args[1], "always") == 0) {
5314 /* enable a graceful server shutdown on an HTTP 404 response */
5315 curproxy->options &= ~PR_O_REUSE_MASK;
5316 curproxy->options |= PR_O_REUSE_ALWS;
5317 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5318 goto out;
5319 }
5320 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005321 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
5325 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005326 else if (!strcmp(args[0], "http-check")) {
5327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005329
5330 if (strcmp(args[1], "disable-on-404") == 0) {
5331 /* enable a graceful server shutdown on an HTTP 404 response */
5332 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005333 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5334 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005335 }
Willy Tarreauef781042010-01-27 11:53:01 +01005336 else if (strcmp(args[1], "send-state") == 0) {
5337 /* enable emission of the apparent state of a server in HTTP checks */
5338 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005339 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5340 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005341 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005342 else if (strcmp(args[1], "expect") == 0) {
5343 const char *ptr_arg;
5344 int cur_arg;
5345
5346 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5347 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351
5352 cur_arg = 2;
5353 /* consider exclamation marks, sole or at the beginning of a word */
5354 while (*(ptr_arg = args[cur_arg])) {
5355 while (*ptr_arg == '!') {
5356 curproxy->options2 ^= PR_O2_EXP_INV;
5357 ptr_arg++;
5358 }
5359 if (*ptr_arg)
5360 break;
5361 cur_arg++;
5362 }
5363 /* now ptr_arg points to the beginning of a word past any possible
5364 * exclamation mark, and cur_arg is the argument which holds this word.
5365 */
5366 if (strcmp(ptr_arg, "status") == 0) {
5367 if (!*(args[cur_arg + 1])) {
5368 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5369 file, linenum, args[0], args[1], ptr_arg);
5370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
5372 }
5373 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005374 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005375 curproxy->expect_str = strdup(args[cur_arg + 1]);
5376 }
5377 else if (strcmp(ptr_arg, "string") == 0) {
5378 if (!*(args[cur_arg + 1])) {
5379 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5380 file, linenum, args[0], args[1], ptr_arg);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005385 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005386 curproxy->expect_str = strdup(args[cur_arg + 1]);
5387 }
5388 else if (strcmp(ptr_arg, "rstatus") == 0) {
5389 if (!*(args[cur_arg + 1])) {
5390 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5391 file, linenum, args[0], args[1], ptr_arg);
5392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 }
5395 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005396 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005397 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005398 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005399 free(curproxy->expect_regex);
5400 curproxy->expect_regex = NULL;
5401 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005402 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005403 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5404 error = NULL;
5405 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5406 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5407 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5408 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412 }
5413 else if (strcmp(ptr_arg, "rstring") == 0) {
5414 if (!*(args[cur_arg + 1])) {
5415 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5416 file, linenum, args[0], args[1], ptr_arg);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005421 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005422 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005423 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005424 free(curproxy->expect_regex);
5425 curproxy->expect_regex = NULL;
5426 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005427 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005428 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5429 error = NULL;
5430 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5431 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5432 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5433 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
5437 }
5438 else {
5439 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5440 file, linenum, args[0], args[1], ptr_arg);
5441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
5443 }
5444 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005445 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005446 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 +02005447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005449 }
5450 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005451 else if (!strcmp(args[0], "tcp-check")) {
5452 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5453 err_code |= ERR_WARN;
5454
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005455 if (strcmp(args[1], "comment") == 0) {
5456 int cur_arg;
5457 struct tcpcheck_rule *tcpcheck;
5458
5459 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005460 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005461 tcpcheck->action = TCPCHK_ACT_COMMENT;
5462
5463 if (!*args[cur_arg + 1]) {
5464 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5465 file, linenum, args[cur_arg]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
5469
5470 tcpcheck->comment = strdup(args[cur_arg + 1]);
5471
5472 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005473 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5474 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005475 }
5476 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005477 const char *ptr_arg;
5478 int cur_arg;
5479 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005480
5481 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005482 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5483 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5484 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5485 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5486 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005487
Willy Tarreau5581c272015-05-13 12:24:53 +02005488 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5489 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5490 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5491 file, linenum);
5492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005494 }
5495
5496 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005497 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005498 tcpcheck->action = TCPCHK_ACT_CONNECT;
5499
5500 /* parsing each parameters to fill up the rule */
5501 while (*(ptr_arg = args[cur_arg])) {
5502 /* tcp port */
5503 if (strcmp(args[cur_arg], "port") == 0) {
5504 if ( (atol(args[cur_arg + 1]) > 65535) ||
5505 (atol(args[cur_arg + 1]) < 1) ){
5506 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5507 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
5510 }
5511 tcpcheck->port = atol(args[cur_arg + 1]);
5512 cur_arg += 2;
5513 }
5514 /* send proxy protocol */
5515 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5516 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5517 cur_arg++;
5518 }
5519#ifdef USE_OPENSSL
5520 else if (strcmp(args[cur_arg], "ssl") == 0) {
5521 curproxy->options |= PR_O_TCPCHK_SSL;
5522 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5523 cur_arg++;
5524 }
5525#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005526 /* comment for this tcpcheck line */
5527 else if (strcmp(args[cur_arg], "comment") == 0) {
5528 if (!*args[cur_arg + 1]) {
5529 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5530 file, linenum, args[cur_arg]);
5531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 }
5534 tcpcheck->comment = strdup(args[cur_arg + 1]);
5535 cur_arg += 2;
5536 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005537 else {
5538#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005539 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 +01005540#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005541 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 +01005542#endif /* USE_OPENSSL */
5543 file, linenum, args[0], args[1], args[cur_arg]);
5544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
5546 }
5547
5548 }
5549
5550 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5551 }
5552 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005553 if (! *(args[2]) ) {
5554 /* SEND string expected */
5555 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5556 file, linenum, args[0], args[1], args[2]);
5557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
5559 } else {
5560 struct tcpcheck_rule *tcpcheck;
5561
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005562 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005563
5564 tcpcheck->action = TCPCHK_ACT_SEND;
5565 tcpcheck->string_len = strlen(args[2]);
5566 tcpcheck->string = strdup(args[2]);
5567 tcpcheck->expect_regex = NULL;
5568
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005569 /* comment for this tcpcheck line */
5570 if (strcmp(args[3], "comment") == 0) {
5571 if (!*args[4]) {
5572 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5573 file, linenum, args[3]);
5574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
5576 }
5577 tcpcheck->comment = strdup(args[4]);
5578 }
5579
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5581 }
5582 }
5583 else if (strcmp(args[1], "send-binary") == 0) {
5584 if (! *(args[2]) ) {
5585 /* SEND binary string expected */
5586 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5587 file, linenum, args[0], args[1], args[2]);
5588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
5590 } else {
5591 struct tcpcheck_rule *tcpcheck;
5592 char *err = NULL;
5593
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005594 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005595
5596 tcpcheck->action = TCPCHK_ACT_SEND;
5597 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5598 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5599 file, linenum, args[0], args[1], args[2], err);
5600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
5602 }
5603 tcpcheck->expect_regex = NULL;
5604
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005605 /* comment for this tcpcheck line */
5606 if (strcmp(args[3], "comment") == 0) {
5607 if (!*args[4]) {
5608 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5609 file, linenum, args[3]);
5610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
5612 }
5613 tcpcheck->comment = strdup(args[4]);
5614 }
5615
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005616 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5617 }
5618 }
5619 else if (strcmp(args[1], "expect") == 0) {
5620 const char *ptr_arg;
5621 int cur_arg;
5622 int inverse = 0;
5623
5624 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5625 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
5629
5630 cur_arg = 2;
5631 /* consider exclamation marks, sole or at the beginning of a word */
5632 while (*(ptr_arg = args[cur_arg])) {
5633 while (*ptr_arg == '!') {
5634 inverse = !inverse;
5635 ptr_arg++;
5636 }
5637 if (*ptr_arg)
5638 break;
5639 cur_arg++;
5640 }
5641 /* now ptr_arg points to the beginning of a word past any possible
5642 * exclamation mark, and cur_arg is the argument which holds this word.
5643 */
5644 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005645 struct tcpcheck_rule *tcpcheck;
5646 char *err = NULL;
5647
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005648 if (!*(args[cur_arg + 1])) {
5649 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5650 file, linenum, args[0], args[1], ptr_arg);
5651 err_code |= ERR_ALERT | ERR_FATAL;
5652 goto out;
5653 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005654
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005655 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005656
5657 tcpcheck->action = TCPCHK_ACT_EXPECT;
5658 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5659 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5660 file, linenum, args[0], args[1], args[2], err);
5661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
5663 }
5664 tcpcheck->expect_regex = NULL;
5665 tcpcheck->inverse = inverse;
5666
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005667 /* tcpcheck comment */
5668 cur_arg += 2;
5669 if (strcmp(args[cur_arg], "comment") == 0) {
5670 if (!*args[cur_arg + 1]) {
5671 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5672 file, linenum, args[cur_arg + 1]);
5673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
5675 }
5676 tcpcheck->comment = strdup(args[cur_arg + 1]);
5677 }
5678
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005679 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5680 }
5681 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005682 struct tcpcheck_rule *tcpcheck;
5683
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005684 if (!*(args[cur_arg + 1])) {
5685 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5686 file, linenum, args[0], args[1], ptr_arg);
5687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
5689 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005690
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005691 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005692
5693 tcpcheck->action = TCPCHK_ACT_EXPECT;
5694 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5695 tcpcheck->string = strdup(args[cur_arg + 1]);
5696 tcpcheck->expect_regex = NULL;
5697 tcpcheck->inverse = inverse;
5698
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005699 /* tcpcheck comment */
5700 cur_arg += 2;
5701 if (strcmp(args[cur_arg], "comment") == 0) {
5702 if (!*args[cur_arg + 1]) {
5703 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5704 file, linenum, args[cur_arg + 1]);
5705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
5707 }
5708 tcpcheck->comment = strdup(args[cur_arg + 1]);
5709 }
5710
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005711 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5712 }
5713 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005714 struct tcpcheck_rule *tcpcheck;
5715
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005716 if (!*(args[cur_arg + 1])) {
5717 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5718 file, linenum, args[0], args[1], ptr_arg);
5719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
5721 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005722
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005723 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005724
5725 tcpcheck->action = TCPCHK_ACT_EXPECT;
5726 tcpcheck->string_len = 0;
5727 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005728 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5729 error = NULL;
5730 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5731 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5732 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5733 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
5736 }
5737 tcpcheck->inverse = inverse;
5738
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005739 /* tcpcheck comment */
5740 cur_arg += 2;
5741 if (strcmp(args[cur_arg], "comment") == 0) {
5742 if (!*args[cur_arg + 1]) {
5743 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5744 file, linenum, args[cur_arg + 1]);
5745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
5747 }
5748 tcpcheck->comment = strdup(args[cur_arg + 1]);
5749 }
5750
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005751 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5752 }
5753 else {
5754 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5755 file, linenum, args[0], args[1], ptr_arg);
5756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
5758 }
5759 }
5760 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005761 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
5764 }
5765 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005766 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005767 if (curproxy == &defproxy) {
5768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005771 }
5772
Willy Tarreaub80c2302007-11-30 20:51:32 +01005773 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005774 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005775
5776 if (strcmp(args[1], "fail") == 0) {
5777 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005778 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005779 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5780 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005781 err_code |= ERR_ALERT | ERR_FATAL;
5782 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005783 }
5784
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005785 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5786 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5787 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005788 err_code |= ERR_ALERT | ERR_FATAL;
5789 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005790 }
5791 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5792 }
5793 else {
5794 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005797 }
5798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799#ifdef TPROXY
5800 else if (!strcmp(args[0], "transparent")) {
5801 /* enable transparent proxy connections */
5802 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005803 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 }
5806#endif
5807 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005808 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005810
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 if (*(args[1]) == 0) {
5812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005813 err_code |= ERR_ALERT | ERR_FATAL;
5814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815 }
5816 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005817 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005820 else if (!strcmp(args[0], "backlog")) { /* backlog */
5821 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005822 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005823
5824 if (*(args[1]) == 0) {
5825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005826 err_code |= ERR_ALERT | ERR_FATAL;
5827 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005828 }
5829 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005830 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5831 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005832 }
Willy Tarreau86034312006-12-29 00:10:33 +01005833 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005836
Willy Tarreau86034312006-12-29 00:10:33 +01005837 if (*(args[1]) == 0) {
5838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005841 }
5842 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005843 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5844 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5847 if (*(args[1]) == 0) {
5848 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005849 err_code |= ERR_ALERT | ERR_FATAL;
5850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005852 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5853 if (err) {
5854 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5855 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005856 err_code |= ERR_ALERT | ERR_FATAL;
5857 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005858 }
5859 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005860 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 }
5863 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005864 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005865 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005866 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005867
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 if (curproxy == &defproxy) {
5869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005870 err_code |= ERR_ALERT | ERR_FATAL;
5871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005873 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005874 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005875
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005876 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005877 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005878 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005879 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005880 goto out;
5881 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005882
5883 proto = protocol_by_family(sk->ss_family);
5884 if (!proto || !proto->connect) {
5885 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5886 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005887 err_code |= ERR_ALERT | ERR_FATAL;
5888 goto out;
5889 }
5890
5891 if (port1 != port2) {
5892 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5893 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005894 err_code |= ERR_ALERT | ERR_FATAL;
5895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005897
5898 if (!port1) {
5899 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5900 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005901 err_code |= ERR_ALERT | ERR_FATAL;
5902 goto out;
5903 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005904
William Lallemanddf1425a2015-04-28 20:17:49 +02005905 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5906 goto out;
5907
Willy Tarreaud5191e72010-02-09 20:50:45 +01005908 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005909 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 }
5911 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005912 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005913 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005914
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005915 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5916 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005920 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005921 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005922 /**
5923 * The syntax for hash-type config element is
5924 * hash-type {map-based|consistent} [[<algo>] avalanche]
5925 *
5926 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5927 */
5928 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005929
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005930 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5931 err_code |= ERR_WARN;
5932
5933 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005934 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5935 }
5936 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005937 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5938 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005939 else if (strcmp(args[1], "avalanche") == 0) {
5940 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]);
5941 err_code |= ERR_ALERT | ERR_FATAL;
5942 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005943 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005944 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005945 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005946 err_code |= ERR_ALERT | ERR_FATAL;
5947 goto out;
5948 }
Bhaskar98634f02013-10-29 23:30:51 -04005949
5950 /* set the hash function to use */
5951 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005952 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005953 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005954
5955 /* if consistent with no argument, then avalanche modifier is also applied */
5956 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5957 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005958 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005959 /* set the hash function */
5960 if (!strcmp(args[2], "sdbm")) {
5961 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5962 }
5963 else if (!strcmp(args[2], "djb2")) {
5964 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005965 }
5966 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005967 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005968 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005969 else if (!strcmp(args[2], "crc32")) {
5970 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5971 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005972 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005973 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 -05005974 err_code |= ERR_ALERT | ERR_FATAL;
5975 goto out;
5976 }
5977
5978 /* set the hash modifier */
5979 if (!strcmp(args[3], "avalanche")) {
5980 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5981 }
5982 else if (*args[3]) {
5983 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5984 err_code |= ERR_ALERT | ERR_FATAL;
5985 goto out;
5986 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005987 }
William Lallemanda73203e2012-03-12 12:48:57 +01005988 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005989 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5990 if (*(args[1]) == 0) {
5991 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5992 err_code |= ERR_ALERT | ERR_FATAL;
5993 goto out;
5994 }
5995 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5996 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5997 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001 }
William Lallemanda73203e2012-03-12 12:48:57 +01006002 else if (strcmp(args[0], "unique-id-format") == 0) {
6003 if (!*(args[1])) {
6004 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6005 err_code |= ERR_ALERT | ERR_FATAL;
6006 goto out;
6007 }
William Lallemand3203ff42012-11-11 17:30:56 +01006008 if (*(args[2])) {
6009 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6010 err_code |= ERR_ALERT | ERR_FATAL;
6011 goto out;
6012 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006013 free(curproxy->conf.uniqueid_format_string);
6014 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006015
Willy Tarreau62a61232013-04-12 18:13:46 +02006016 free(curproxy->conf.uif_file);
6017 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6018 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006019 }
William Lallemanda73203e2012-03-12 12:48:57 +01006020
6021 else if (strcmp(args[0], "unique-id-header") == 0) {
6022 if (!*(args[1])) {
6023 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
6026 }
6027 free(curproxy->header_unique_id);
6028 curproxy->header_unique_id = strdup(args[1]);
6029 }
6030
William Lallemand723b73a2012-02-08 16:37:49 +01006031 else if (strcmp(args[0], "log-format") == 0) {
6032 if (!*(args[1])) {
6033 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6034 err_code |= ERR_ALERT | ERR_FATAL;
6035 goto out;
6036 }
William Lallemand3203ff42012-11-11 17:30:56 +01006037 if (*(args[2])) {
6038 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6039 err_code |= ERR_ALERT | ERR_FATAL;
6040 goto out;
6041 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006042
Willy Tarreau62a61232013-04-12 18:13:46 +02006043 if (curproxy->conf.logformat_string != default_http_log_format &&
6044 curproxy->conf.logformat_string != default_tcp_log_format &&
6045 curproxy->conf.logformat_string != clf_http_log_format)
6046 free(curproxy->conf.logformat_string);
6047 curproxy->conf.logformat_string = strdup(args[1]);
6048
6049 free(curproxy->conf.lfs_file);
6050 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6051 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006052
6053 /* get a chance to improve log-format error reporting by
6054 * reporting the correct line-number when possible.
6055 */
6056 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6057 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6058 file, linenum, curproxy->id);
6059 err_code |= ERR_WARN;
6060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006062 else if (!strcmp(args[0], "log-format-sd")) {
6063 if (!*(args[1])) {
6064 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
6067 }
6068 if (*(args[2])) {
6069 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6070 err_code |= ERR_ALERT | ERR_FATAL;
6071 goto out;
6072 }
6073
6074 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6075 free(curproxy->conf.logformat_sd_string);
6076 curproxy->conf.logformat_sd_string = strdup(args[1]);
6077
6078 free(curproxy->conf.lfsd_file);
6079 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6080 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6081
6082 /* get a chance to improve log-format-sd error reporting by
6083 * reporting the correct line-number when possible.
6084 */
6085 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6086 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6087 file, linenum, curproxy->id);
6088 err_code |= ERR_WARN;
6089 }
6090 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006091 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6092 if (*(args[1]) == 0) {
6093 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6094 err_code |= ERR_ALERT | ERR_FATAL;
6095 goto out;
6096 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006097 chunk_destroy(&curproxy->log_tag);
6098 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006099 }
William Lallemand0f99e342011-10-12 17:50:54 +02006100 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6101 /* delete previous herited or defined syslog servers */
6102 struct logsrv *back;
6103
6104 if (*(args[1]) != 0) {
6105 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6106 err_code |= ERR_ALERT | ERR_FATAL;
6107 goto out;
6108 }
6109
William Lallemand723b73a2012-02-08 16:37:49 +01006110 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6111 LIST_DEL(&tmplogsrv->list);
6112 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006113 }
6114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006116 struct logsrv *logsrv;
6117
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006119 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006120 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006121 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006122 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006123 LIST_INIT(&node->list);
6124 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006126 }
6127 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006128 struct sockaddr_storage *sk;
6129 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006130 int arg = 0;
6131 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006132
Vincent Bernat02779b62016-04-03 13:48:43 +02006133 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134
Willy Tarreau18324f52014-06-27 18:10:07 +02006135 /* just after the address, a length may be specified */
6136 if (strcmp(args[arg+2], "len") == 0) {
6137 len = atoi(args[arg+3]);
6138 if (len < 80 || len > 65535) {
6139 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6140 file, linenum, args[arg+3]);
6141 err_code |= ERR_ALERT | ERR_FATAL;
6142 goto out;
6143 }
6144 logsrv->maxlen = len;
6145
6146 /* skip these two args */
6147 arg += 2;
6148 }
6149 else
6150 logsrv->maxlen = MAX_SYSLOG_LEN;
6151
6152 if (logsrv->maxlen > global.max_syslog_len) {
6153 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006154 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6155 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6156 logline = my_realloc2(logline, global.max_syslog_len + 1);
6157 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006158 }
6159
Dragan Dosen1322d092015-09-22 16:05:32 +02006160 /* after the length, a format may be specified */
6161 if (strcmp(args[arg+2], "format") == 0) {
6162 logsrv->format = get_log_format(args[arg+3]);
6163 if (logsrv->format < 0) {
6164 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6165 err_code |= ERR_ALERT | ERR_FATAL;
6166 goto out;
6167 }
6168
6169 /* skip these two args */
6170 arg += 2;
6171 }
6172
William Lallemanddf1425a2015-04-28 20:17:49 +02006173 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6174 goto out;
6175
Willy Tarreau18324f52014-06-27 18:10:07 +02006176 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006177 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006178 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006179 err_code |= ERR_ALERT | ERR_FATAL;
6180 goto out;
6181
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 }
6183
William Lallemand0f99e342011-10-12 17:50:54 +02006184 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006185 if (*(args[arg+3])) {
6186 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006187 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006188 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006189 err_code |= ERR_ALERT | ERR_FATAL;
6190 goto out;
6191
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192 }
6193 }
6194
William Lallemand0f99e342011-10-12 17:50:54 +02006195 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006196 if (*(args[arg+4])) {
6197 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006198 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006199 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
6202
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006203 }
6204 }
6205
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006206 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006207 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006208 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006209 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006210 goto out;
6211 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006212
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006213 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006214
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006215 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006216 if (port1 != port2) {
6217 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6218 file, linenum, args[0], args[1]);
6219 err_code |= ERR_ALERT | ERR_FATAL;
6220 goto out;
6221 }
6222
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006223 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006224 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225 }
William Lallemand0f99e342011-10-12 17:50:54 +02006226
6227 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006228 }
6229 else {
6230 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6231 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006234 }
6235 }
6236 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006237 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006238 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006239 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006240 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006241
Willy Tarreau977b8e42006-12-29 14:19:17 +01006242 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006243 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006244
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006246 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6247 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006248 err_code |= ERR_ALERT | ERR_FATAL;
6249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006250 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006251
6252 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006253 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6254 free(curproxy->conn_src.iface_name);
6255 curproxy->conn_src.iface_name = NULL;
6256 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006257
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006258 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006259 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006260 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006261 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006262 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006263 goto out;
6264 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006265
6266 proto = protocol_by_family(sk->ss_family);
6267 if (!proto || !proto->connect) {
6268 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006269 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006270 err_code |= ERR_ALERT | ERR_FATAL;
6271 goto out;
6272 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006273
6274 if (port1 != port2) {
6275 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6276 file, linenum, args[0], args[1]);
6277 err_code |= ERR_ALERT | ERR_FATAL;
6278 goto out;
6279 }
6280
Willy Tarreauef9a3602012-12-08 22:29:20 +01006281 curproxy->conn_src.source_addr = *sk;
6282 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006283
6284 cur_arg = 2;
6285 while (*(args[cur_arg])) {
6286 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006287#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006288 if (!*args[cur_arg + 1]) {
6289 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6290 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006291 err_code |= ERR_ALERT | ERR_FATAL;
6292 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006293 }
6294
6295 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006296 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6297 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006298 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006299 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6300 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006301 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6302 char *name, *end;
6303
6304 name = args[cur_arg+1] + 7;
6305 while (isspace(*name))
6306 name++;
6307
6308 end = name;
6309 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6310 end++;
6311
Willy Tarreauef9a3602012-12-08 22:29:20 +01006312 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6313 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6314 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6315 curproxy->conn_src.bind_hdr_len = end - name;
6316 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6317 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6318 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006319
6320 /* now look for an occurrence number */
6321 while (isspace(*end))
6322 end++;
6323 if (*end == ',') {
6324 end++;
6325 name = end;
6326 if (*end == '-')
6327 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006328 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006329 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006330 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006331 }
6332
Willy Tarreauef9a3602012-12-08 22:29:20 +01006333 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006334 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6335 " occurrences values smaller than %d.\n",
6336 file, linenum, MAX_HDR_HISTORY);
6337 err_code |= ERR_ALERT | ERR_FATAL;
6338 goto out;
6339 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006340 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006341 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006342
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006343 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006344 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006345 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006346 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006347 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006348 goto out;
6349 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006350
6351 proto = protocol_by_family(sk->ss_family);
6352 if (!proto || !proto->connect) {
6353 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6354 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006355 err_code |= ERR_ALERT | ERR_FATAL;
6356 goto out;
6357 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006358
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006359 if (port1 != port2) {
6360 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6361 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006362 err_code |= ERR_ALERT | ERR_FATAL;
6363 goto out;
6364 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006365 curproxy->conn_src.tproxy_addr = *sk;
6366 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006367 }
6368 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006369#else /* no TPROXY support */
6370 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006371 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006372 err_code |= ERR_ALERT | ERR_FATAL;
6373 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006374#endif
6375 cur_arg += 2;
6376 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006377 }
6378
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006379 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6380#ifdef SO_BINDTODEVICE
6381 if (!*args[cur_arg + 1]) {
6382 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6383 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006384 err_code |= ERR_ALERT | ERR_FATAL;
6385 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006386 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006387 free(curproxy->conn_src.iface_name);
6388 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6389 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006390 global.last_checks |= LSTCHK_NETADM;
6391#else
6392 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6393 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006394 err_code |= ERR_ALERT | ERR_FATAL;
6395 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006396#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006397 cur_arg += 2;
6398 continue;
6399 }
6400 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006401 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006402 err_code |= ERR_ALERT | ERR_FATAL;
6403 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006404 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006406 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6407 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6408 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006409 err_code |= ERR_ALERT | ERR_FATAL;
6410 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006411 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6415 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006416 err_code |= ERR_ALERT | ERR_FATAL;
6417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006419
6420 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006421 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006422 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006423 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 }
6426 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006428 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006429 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006432 }
6433 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006434 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006435 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006436 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006437 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439 }
6440 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006441 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006442 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006443 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006444 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 }
6447 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006448 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006449 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006450 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006451 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006454 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006455 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006456 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006457 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006459 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006463 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006465 err_code |= ERR_ALERT | ERR_FATAL;
6466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006468
6469 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006470 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006471 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006472 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 }
6475 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006476 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006477 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006478 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 }
6482 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006484 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006485 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 }
6489 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006491 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006492 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 }
6496 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006497 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006498 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006499 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006500 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006503 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006504 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006505 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006506 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006507 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006508 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006510 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006511 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006512
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 if (curproxy == &defproxy) {
6514 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006515 err_code |= ERR_ALERT | ERR_FATAL;
6516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006518 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006519 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520
Willy Tarreaubaaee002006-06-26 02:48:02 +02006521 if (*(args[1]) == 0) {
6522 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006523 err_code |= ERR_ALERT | ERR_FATAL;
6524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006526
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006527 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006528 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6529 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6530 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006531 err_code |= ERR_ALERT | ERR_FATAL;
6532 goto out;
6533 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006534 err_code |= warnif_cond_conflicts(cond,
6535 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6536 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006537 }
6538 else if (*args[2]) {
6539 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6540 file, linenum, args[0], args[2]);
6541 err_code |= ERR_ALERT | ERR_FATAL;
6542 goto out;
6543 }
6544
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006545 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006546 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006547 wl->s = strdup(args[1]);
6548 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006549 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550 }
6551 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006552 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6554 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006555 err_code |= ERR_ALERT | ERR_FATAL;
6556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006557 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006558
Willy Tarreauade5ec42010-01-28 19:33:49 +01006559 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006560 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006561 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006562 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006564 }
6565 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006566 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006567 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006568 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006569 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006571 }
6572 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006573 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006574 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006575 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006576 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 }
6579 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006580 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006583 err_code |= ERR_ALERT | ERR_FATAL;
6584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585 }
6586
Willy Tarreauade5ec42010-01-28 19:33:49 +01006587 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006588 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006589 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006590 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 }
6593 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006594 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006595 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006596 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006597 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599 }
6600 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006601 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006602 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006603 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006604 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606 }
6607 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006608 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006609
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 if (curproxy == &defproxy) {
6611 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006612 err_code |= ERR_ALERT | ERR_FATAL;
6613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006614 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006615 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006616 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617
Willy Tarreaubaaee002006-06-26 02:48:02 +02006618 if (*(args[1]) == 0) {
6619 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006620 err_code |= ERR_ALERT | ERR_FATAL;
6621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006622 }
6623
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006624 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006625 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6626 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6627 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006628 err_code |= ERR_ALERT | ERR_FATAL;
6629 goto out;
6630 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006631 err_code |= warnif_cond_conflicts(cond,
6632 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6633 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006634 }
6635 else if (*args[2]) {
6636 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6637 file, linenum, args[0], args[2]);
6638 err_code |= ERR_ALERT | ERR_FATAL;
6639 goto out;
6640 }
6641
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006642 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006643 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006644 wl->s = strdup(args[1]);
6645 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006646 }
6647 else if (!strcmp(args[0], "errorloc") ||
6648 !strcmp(args[0], "errorloc302") ||
6649 !strcmp(args[0], "errorloc303")) { /* error location */
6650 int errnum, errlen;
6651 char *err;
6652
Willy Tarreau977b8e42006-12-29 14:19:17 +01006653 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006654 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006655
Willy Tarreaubaaee002006-06-26 02:48:02 +02006656 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006657 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006658 err_code |= ERR_ALERT | ERR_FATAL;
6659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006660 }
6661
6662 errnum = atol(args[1]);
6663 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006664 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6665 err = malloc(errlen);
6666 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006667 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006668 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6669 err = malloc(errlen);
6670 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006671 }
6672
Willy Tarreau0f772532006-12-23 20:51:41 +01006673 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6674 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006675 chunk_destroy(&curproxy->errmsg[rc]);
6676 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006677 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006679 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006680
6681 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006682 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6683 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006684 free(err);
6685 }
6686 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006687 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6688 int errnum, errlen, fd;
6689 char *err;
6690 struct stat stat;
6691
6692 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006693 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006694
6695 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006696 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006697 err_code |= ERR_ALERT | ERR_FATAL;
6698 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006699 }
6700
6701 fd = open(args[2], O_RDONLY);
6702 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6703 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6704 file, linenum, args[2], args[1]);
6705 if (fd >= 0)
6706 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006707 err_code |= ERR_ALERT | ERR_FATAL;
6708 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006709 }
6710
Willy Tarreau27a674e2009-08-17 07:23:33 +02006711 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006712 errlen = stat.st_size;
6713 } else {
6714 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006715 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006716 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006717 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006718 }
6719
6720 err = malloc(errlen); /* malloc() must succeed during parsing */
6721 errnum = read(fd, err, errlen);
6722 if (errnum != errlen) {
6723 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6724 file, linenum, args[2], args[1]);
6725 close(fd);
6726 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006727 err_code |= ERR_ALERT | ERR_FATAL;
6728 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006729 }
6730 close(fd);
6731
6732 errnum = atol(args[1]);
6733 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6734 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006735 chunk_destroy(&curproxy->errmsg[rc]);
6736 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006737 break;
6738 }
6739 }
6740
6741 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006742 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6743 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006744 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006745 free(err);
6746 }
6747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006748 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006749 struct cfg_kw_list *kwl;
6750 int index;
6751
6752 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6753 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6754 if (kwl->kw[index].section != CFG_LISTEN)
6755 continue;
6756 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6757 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006758 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006759 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006760 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006761 err_code |= ERR_ALERT | ERR_FATAL;
6762 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006763 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006764 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006765 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006766 err_code |= ERR_WARN;
6767 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006768 }
Willy Tarreau93893792009-07-23 13:19:11 +02006769 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006770 }
6771 }
6772 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006773
Willy Tarreau6daf3432008-01-22 16:44:08 +01006774 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006775 err_code |= ERR_ALERT | ERR_FATAL;
6776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006777 }
Willy Tarreau93893792009-07-23 13:19:11 +02006778 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006779 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006780 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006781}
6782
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006783int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006784cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6785{
6786#ifdef CONFIG_HAP_NS
6787 const char *err;
6788 const char *item = args[0];
6789
6790 if (!strcmp(item, "namespace_list")) {
6791 return 0;
6792 }
6793 else if (!strcmp(item, "namespace")) {
6794 size_t idx = 1;
6795 const char *current;
6796 while (*(current = args[idx++])) {
6797 err = invalid_char(current);
6798 if (err) {
6799 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6800 file, linenum, *err, item, current);
6801 return ERR_ALERT | ERR_FATAL;
6802 }
6803
6804 if (netns_store_lookup(current, strlen(current))) {
6805 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6806 file, linenum, current);
6807 return ERR_ALERT | ERR_FATAL;
6808 }
6809 if (!netns_store_insert(current)) {
6810 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6811 file, linenum, current);
6812 return ERR_ALERT | ERR_FATAL;
6813 }
6814 }
6815 }
6816
6817 return 0;
6818#else
6819 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6820 file, linenum);
6821 return ERR_ALERT | ERR_FATAL;
6822#endif
6823}
6824
6825int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006826cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6827{
6828
6829 int err_code = 0;
6830 const char *err;
6831
6832 if (!strcmp(args[0], "userlist")) { /* new userlist */
6833 struct userlist *newul;
6834
6835 if (!*args[1]) {
6836 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6837 file, linenum, args[0]);
6838 err_code |= ERR_ALERT | ERR_FATAL;
6839 goto out;
6840 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006841 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6842 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006843
6844 err = invalid_char(args[1]);
6845 if (err) {
6846 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6847 file, linenum, *err, args[0], args[1]);
6848 err_code |= ERR_ALERT | ERR_FATAL;
6849 goto out;
6850 }
6851
6852 for (newul = userlist; newul; newul = newul->next)
6853 if (!strcmp(newul->name, args[1])) {
6854 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6855 file, linenum, args[1]);
6856 err_code |= ERR_WARN;
6857 goto out;
6858 }
6859
Vincent Bernat02779b62016-04-03 13:48:43 +02006860 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006861 if (!newul) {
6862 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6863 err_code |= ERR_ALERT | ERR_ABORT;
6864 goto out;
6865 }
6866
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006867 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006868 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006869 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6870 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006871 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006872 goto out;
6873 }
6874
6875 newul->next = userlist;
6876 userlist = newul;
6877
6878 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006879 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006880 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006881 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006882
6883 if (!*args[1]) {
6884 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6885 file, linenum, args[0]);
6886 err_code |= ERR_ALERT | ERR_FATAL;
6887 goto out;
6888 }
6889
6890 err = invalid_char(args[1]);
6891 if (err) {
6892 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6893 file, linenum, *err, args[0], args[1]);
6894 err_code |= ERR_ALERT | ERR_FATAL;
6895 goto out;
6896 }
6897
William Lallemand4ac9f542015-05-28 18:03:51 +02006898 if (!userlist)
6899 goto out;
6900
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006901 for (ag = userlist->groups; ag; ag = ag->next)
6902 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006903 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6904 file, linenum, args[1], userlist->name);
6905 err_code |= ERR_ALERT;
6906 goto out;
6907 }
6908
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006909 ag = calloc(1, sizeof(*ag));
6910 if (!ag) {
6911 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6912 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006913 goto out;
6914 }
6915
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006916 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006917 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006918 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6919 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006920 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006921 goto out;
6922 }
6923
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006924 cur_arg = 2;
6925
6926 while (*args[cur_arg]) {
6927 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006928 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006929 cur_arg += 2;
6930 continue;
6931 } else {
6932 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6933 file, linenum, args[0]);
6934 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006935 free(ag->groupusers);
6936 free(ag->name);
6937 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006938 goto out;
6939 }
6940 }
6941
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006942 ag->next = userlist->groups;
6943 userlist->groups = ag;
6944
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006945 } else if (!strcmp(args[0], "user")) { /* new user */
6946 struct auth_users *newuser;
6947 int cur_arg;
6948
6949 if (!*args[1]) {
6950 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6951 file, linenum, args[0]);
6952 err_code |= ERR_ALERT | ERR_FATAL;
6953 goto out;
6954 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006955 if (!userlist)
6956 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006957
6958 for (newuser = userlist->users; newuser; newuser = newuser->next)
6959 if (!strcmp(newuser->user, args[1])) {
6960 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6961 file, linenum, args[1], userlist->name);
6962 err_code |= ERR_ALERT;
6963 goto out;
6964 }
6965
Vincent Bernat02779b62016-04-03 13:48:43 +02006966 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006967 if (!newuser) {
6968 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6969 err_code |= ERR_ALERT | ERR_ABORT;
6970 goto out;
6971 }
6972
6973 newuser->user = strdup(args[1]);
6974
6975 newuser->next = userlist->users;
6976 userlist->users = newuser;
6977
6978 cur_arg = 2;
6979
6980 while (*args[cur_arg]) {
6981 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006982#ifdef CONFIG_HAP_CRYPT
6983 if (!crypt("", args[cur_arg + 1])) {
6984 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6985 file, linenum, newuser->user);
6986 err_code |= ERR_ALERT | ERR_FATAL;
6987 goto out;
6988 }
6989#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006990 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6991 file, linenum);
6992 err_code |= ERR_ALERT;
6993#endif
6994 newuser->pass = strdup(args[cur_arg + 1]);
6995 cur_arg += 2;
6996 continue;
6997 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6998 newuser->pass = strdup(args[cur_arg + 1]);
6999 newuser->flags |= AU_O_INSECURE;
7000 cur_arg += 2;
7001 continue;
7002 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007003 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007004 cur_arg += 2;
7005 continue;
7006 } else {
7007 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7008 file, linenum, args[0]);
7009 err_code |= ERR_ALERT | ERR_FATAL;
7010 goto out;
7011 }
7012 }
7013 } else {
7014 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7015 err_code |= ERR_ALERT | ERR_FATAL;
7016 }
7017
7018out:
7019 return err_code;
7020}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007021
Christopher Faulet79bdef32016-11-04 22:36:15 +01007022int
7023cfg_parse_scope(const char *file, int linenum, char *line)
7024{
7025 char *beg, *end, *scope = NULL;
7026 int err_code = 0;
7027 const char *err;
7028
7029 beg = line + 1;
7030 end = strchr(beg, ']');
7031
7032 /* Detect end of scope declaration */
7033 if (!end || end == beg) {
7034 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7035 file, linenum);
7036 err_code |= ERR_ALERT | ERR_FATAL;
7037 goto out;
7038 }
7039
7040 /* Get scope name and check its validity */
7041 scope = my_strndup(beg, end-beg);
7042 err = invalid_char(scope);
7043 if (err) {
7044 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7045 file, linenum, *err);
7046 err_code |= ERR_ALERT | ERR_ABORT;
7047 goto out;
7048 }
7049
7050 /* Be sure to have a scope declaration alone on its line */
7051 line = end+1;
7052 while (isspace((unsigned char)*line))
7053 line++;
7054 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7055 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7056 file, linenum, *line);
7057 err_code |= ERR_ALERT | ERR_ABORT;
7058 goto out;
7059 }
7060
7061 /* We have a valid scope declaration, save it */
7062 free(cfg_scope);
7063 cfg_scope = scope;
7064 scope = NULL;
7065
7066 out:
7067 free(scope);
7068 return err_code;
7069}
7070
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071/*
7072 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007073 * Returns the error code, 0 if OK, or any combination of :
7074 * - ERR_ABORT: must abort ASAP
7075 * - ERR_FATAL: we can continue parsing but not start the service
7076 * - ERR_WARN: a warning has been emitted
7077 * - ERR_ALERT: an alert has been emitted
7078 * Only the two first ones can stop processing, the two others are just
7079 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007081int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007082{
William Lallemand64e84512015-05-12 14:25:37 +02007083 char *thisline;
7084 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007085 FILE *f;
7086 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007087 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007088 struct cfg_section *cs = NULL;
7089 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007090 int readbytes = 0;
7091
7092 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007093 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007094 return -1;
7095 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007096
David Carlier97880bb2016-04-08 10:35:26 +01007097 if ((f=fopen(file,"r")) == NULL) {
7098 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007099 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101
William Lallemandb2f07452015-05-12 14:27:13 +02007102next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007103 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007104 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007105 char *end;
7106 char *args[MAX_LINE_ARGS + 1];
7107 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007108 int dquote = 0; /* double quote */
7109 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007110
Willy Tarreaubaaee002006-06-26 02:48:02 +02007111 linenum++;
7112
7113 end = line + strlen(line);
7114
William Lallemand64e84512015-05-12 14:25:37 +02007115 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007116 /* Check if we reached the limit and the last char is not \n.
7117 * Watch out for the last line without the terminating '\n'!
7118 */
William Lallemand64e84512015-05-12 14:25:37 +02007119 char *newline;
7120 int newlinesize = linesize * 2;
7121
7122 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7123 if (newline == NULL) {
7124 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7125 file, linenum);
7126 err_code |= ERR_ALERT | ERR_FATAL;
7127 continue;
7128 }
7129
7130 readbytes = linesize - 1;
7131 linesize = newlinesize;
7132 thisline = newline;
7133 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007134 }
7135
William Lallemand64e84512015-05-12 14:25:37 +02007136 readbytes = 0;
7137
Willy Tarreaubaaee002006-06-26 02:48:02 +02007138 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007139 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007140 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007141
Christopher Faulet79bdef32016-11-04 22:36:15 +01007142
7143 if (*line == '[') {/* This is the begining if a scope */
7144 err_code |= cfg_parse_scope(file, linenum, line);
7145 goto next_line;
7146 }
7147
Willy Tarreaubaaee002006-06-26 02:48:02 +02007148 arg = 0;
7149 args[arg] = line;
7150
7151 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007152 if (*line == '"' && !squote) { /* double quote outside single quotes */
7153 if (dquote)
7154 dquote = 0;
7155 else
7156 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007157 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007158 end--;
7159 }
7160 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7161 if (squote)
7162 squote = 0;
7163 else
7164 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007165 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007166 end--;
7167 }
7168 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007169 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7170 * C equivalent value. Other combinations left unchanged (eg: \1).
7171 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007172 int skip = 0;
7173 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7174 *line = line[1];
7175 skip = 1;
7176 }
7177 else if (line[1] == 'r') {
7178 *line = '\r';
7179 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181 else if (line[1] == 'n') {
7182 *line = '\n';
7183 skip = 1;
7184 }
7185 else if (line[1] == 't') {
7186 *line = '\t';
7187 skip = 1;
7188 }
7189 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007190 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007191 unsigned char hex1, hex2;
7192 hex1 = toupper(line[2]) - '0';
7193 hex2 = toupper(line[3]) - '0';
7194 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7195 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7196 *line = (hex1<<4) + hex2;
7197 skip = 3;
7198 }
7199 else {
7200 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007201 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007202 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007203 } else if (line[1] == '"') {
7204 *line = '"';
7205 skip = 1;
7206 } else if (line[1] == '\'') {
7207 *line = '\'';
7208 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007209 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7210 *line = '$';
7211 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007212 }
7213 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007214 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007215 end -= skip;
7216 }
7217 line++;
7218 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007219 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007220 /* end of string, end of loop */
7221 *line = 0;
7222 break;
7223 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007224 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007225 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007226 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007227 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007228 line++;
7229 args[++arg] = line;
7230 }
William Lallemandb2f07452015-05-12 14:27:13 +02007231 else if (dquote && *line == '$') {
7232 /* environment variables are evaluated inside double quotes */
7233 char *var_beg;
7234 char *var_end;
7235 char save_char;
7236 char *value;
7237 int val_len;
7238 int newlinesize;
7239 int braces = 0;
7240
7241 var_beg = line + 1;
7242 var_end = var_beg;
7243
7244 if (*var_beg == '{') {
7245 var_beg++;
7246 var_end++;
7247 braces = 1;
7248 }
7249
7250 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7251 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7252 err_code |= ERR_ALERT | ERR_FATAL;
7253 goto next_line; /* skip current line */
7254 }
7255
7256 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7257 var_end++;
7258
7259 save_char = *var_end;
7260 *var_end = '\0';
7261 value = getenv(var_beg);
7262 *var_end = save_char;
7263 val_len = value ? strlen(value) : 0;
7264
7265 if (braces) {
7266 if (*var_end == '}') {
7267 var_end++;
7268 braces = 0;
7269 } else {
7270 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7271 err_code |= ERR_ALERT | ERR_FATAL;
7272 goto next_line; /* skip current line */
7273 }
7274 }
7275
7276 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7277
7278 /* if not enough space in thisline */
7279 if (newlinesize > linesize) {
7280 char *newline;
7281
7282 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7283 if (newline == NULL) {
7284 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7285 err_code |= ERR_ALERT | ERR_FATAL;
7286 goto next_line; /* slip current line */
7287 }
7288 /* recompute pointers if realloc returns a new pointer */
7289 if (newline != thisline) {
7290 int i;
7291 int diff;
7292
7293 for (i = 0; i <= arg; i++) {
7294 diff = args[i] - thisline;
7295 args[i] = newline + diff;
7296 }
7297
7298 diff = var_end - thisline;
7299 var_end = newline + diff;
7300 diff = end - thisline;
7301 end = newline + diff;
7302 diff = line - thisline;
7303 line = newline + diff;
7304 thisline = newline;
7305 }
7306 linesize = newlinesize;
7307 }
7308
7309 /* insert value inside the line */
7310 memmove(line + val_len, var_end, end - var_end + 1);
7311 memcpy(line, value, val_len);
7312 end += val_len - (var_end - line);
7313 line += val_len;
7314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007315 else {
7316 line++;
7317 }
7318 }
William Lallemandb2f07452015-05-12 14:27:13 +02007319
William Lallemandf9873ba2015-05-05 17:37:14 +02007320 if (dquote) {
7321 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7322 err_code |= ERR_ALERT | ERR_FATAL;
7323 }
7324
7325 if (squote) {
7326 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7327 err_code |= ERR_ALERT | ERR_FATAL;
7328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007329
7330 /* empty line */
7331 if (!**args)
7332 continue;
7333
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007334 if (*line) {
7335 /* we had to stop due to too many args.
7336 * Let's terminate the string, print the offending part then cut the
7337 * last arg.
7338 */
7339 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7340 line++;
7341 *line = '\0';
7342
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007343 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007344 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007345 err_code |= ERR_ALERT | ERR_FATAL;
7346 args[arg] = line;
7347 }
7348
Willy Tarreau540abe42007-05-02 20:50:16 +02007349 /* zero out remaining args and ensure that at least one entry
7350 * is zeroed out.
7351 */
7352 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007353 args[arg] = line;
7354 }
7355
Willy Tarreau3842f002009-06-14 11:39:52 +02007356 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007357 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007358 char *tmp;
7359
Willy Tarreau3842f002009-06-14 11:39:52 +02007360 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007361 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007362 for (arg=0; *args[arg+1]; arg++)
7363 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007364 *tmp = '\0'; // fix the next arg to \0
7365 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007366 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007367 else if (!strcmp(args[0], "default")) {
7368 kwm = KWM_DEF;
7369 for (arg=0; *args[arg+1]; arg++)
7370 args[arg] = args[arg+1]; // shift args after inversion
7371 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007372
William Lallemand0f99e342011-10-12 17:50:54 +02007373 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7374 strcmp(args[0], "log") != 0) {
7375 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007376 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007377 }
7378
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007379 /* detect section start */
7380 list_for_each_entry(ics, &sections, list) {
7381 if (strcmp(args[0], ics->section_name) == 0) {
7382 cursection = ics->section_name;
7383 cs = ics;
7384 break;
7385 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007386 }
7387
Willy Tarreaubaaee002006-06-26 02:48:02 +02007388 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007389 if (cs)
7390 err_code |= cs->section_parser(file, linenum, args, kwm);
7391 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007392 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007393 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007394 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007395
7396 if (err_code & ERR_ABORT)
7397 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007398 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007399 free(cfg_scope);
7400 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007401 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007402 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007403 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007404 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007405}
7406
Willy Tarreau64ab6072014-09-16 12:17:36 +02007407/* This function propagates processes from frontend <from> to backend <to> so
7408 * that it is always guaranteed that a backend pointed to by a frontend is
7409 * bound to all of its processes. After that, if the target is a "listen"
7410 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007411 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007412 * checked first to ensure that <to> is already bound to all processes of
7413 * <from>, there is no risk of looping and we ensure to follow the shortest
7414 * path to the destination.
7415 *
7416 * It is possible to set <to> to NULL for the first call so that the function
7417 * takes care of visiting the initial frontend in <from>.
7418 *
7419 * It is important to note that the function relies on the fact that all names
7420 * have already been resolved.
7421 */
7422void propagate_processes(struct proxy *from, struct proxy *to)
7423{
7424 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007425
7426 if (to) {
7427 /* check whether we need to go down */
7428 if (from->bind_proc &&
7429 (from->bind_proc & to->bind_proc) == from->bind_proc)
7430 return;
7431
7432 if (!from->bind_proc && !to->bind_proc)
7433 return;
7434
7435 to->bind_proc = from->bind_proc ?
7436 (to->bind_proc | from->bind_proc) : 0;
7437
7438 /* now propagate down */
7439 from = to;
7440 }
7441
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007442 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007443 return;
7444
Willy Tarreauf6b70012014-12-18 14:00:43 +01007445 if (from->state == PR_STSTOPPED)
7446 return;
7447
Willy Tarreau64ab6072014-09-16 12:17:36 +02007448 /* default_backend */
7449 if (from->defbe.be)
7450 propagate_processes(from, from->defbe.be);
7451
7452 /* use_backend */
7453 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007454 if (rule->dynamic)
7455 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007456 to = rule->be.backend;
7457 propagate_processes(from, to);
7458 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007459}
7460
Willy Tarreaubb925012009-07-23 13:36:36 +02007461/*
7462 * Returns the error code, 0 if OK, or any combination of :
7463 * - ERR_ABORT: must abort ASAP
7464 * - ERR_FATAL: we can continue parsing but not start the service
7465 * - ERR_WARN: a warning has been emitted
7466 * - ERR_ALERT: an alert has been emitted
7467 * Only the two first ones can stop processing, the two others are just
7468 * indicators.
7469 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007470int check_config_validity()
7471{
7472 int cfgerr = 0;
7473 struct proxy *curproxy = NULL;
7474 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007475 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007476 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007477 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007478 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007479
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007480 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007481 /*
7482 * Now, check for the integrity of all that we have collected.
7483 */
7484
7485 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007486 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007487
Willy Tarreau193b8c62012-11-22 00:17:38 +01007488 if (!global.tune.max_http_hdr)
7489 global.tune.max_http_hdr = MAX_HTTP_HDR;
7490
7491 if (!global.tune.cookie_len)
7492 global.tune.cookie_len = CAPTURE_LEN;
7493
7494 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7495
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007496 /* Post initialisation of the users and groups lists. */
7497 err_code = userlist_postinit();
7498 if (err_code != ERR_NONE)
7499 goto out;
7500
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007501 /* first, we will invert the proxy list order */
7502 curproxy = NULL;
7503 while (proxy) {
7504 struct proxy *next;
7505
7506 next = proxy->next;
7507 proxy->next = curproxy;
7508 curproxy = proxy;
7509 if (!next)
7510 break;
7511 proxy = next;
7512 }
7513
Willy Tarreau419ead82014-09-16 13:41:21 +02007514 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007515 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007516 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007517 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007518 struct act_rule *trule;
7519 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007520 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007521 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007522 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007523
Willy Tarreau050536d2012-10-04 08:47:34 +02007524 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007525 /* proxy ID not set, use automatic numbering with first
7526 * spare entry starting with next_pxid.
7527 */
7528 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7529 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7530 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007531 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007532 next_pxid++;
7533
Willy Tarreau55ea7572007-06-17 19:56:27 +02007534
Willy Tarreaubaaee002006-06-26 02:48:02 +02007535 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007536 /* ensure we don't keep listeners uselessly bound */
7537 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007538 free((void *)curproxy->table.peers.name);
7539 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007540 continue;
7541 }
7542
Willy Tarreau102df612014-05-07 23:56:38 +02007543 /* Check multi-process mode compatibility for the current proxy */
7544
7545 if (curproxy->bind_proc) {
7546 /* an explicit bind-process was specified, let's check how many
7547 * processes remain.
7548 */
David Carliere6c39412015-07-02 07:00:17 +00007549 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007550
7551 curproxy->bind_proc &= nbits(global.nbproc);
7552 if (!curproxy->bind_proc && nbproc == 1) {
7553 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);
7554 curproxy->bind_proc = 1;
7555 }
7556 else if (!curproxy->bind_proc && nbproc > 1) {
7557 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);
7558 curproxy->bind_proc = 0;
7559 }
7560 }
7561
Willy Tarreau3d209582014-05-09 17:06:11 +02007562 /* check and reduce the bind-proc of each listener */
7563 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7564 unsigned long mask;
7565
7566 if (!bind_conf->bind_proc)
7567 continue;
7568
7569 mask = nbits(global.nbproc);
7570 if (curproxy->bind_proc)
7571 mask &= curproxy->bind_proc;
7572 /* mask cannot be null here thanks to the previous checks */
7573
David Carliere6c39412015-07-02 07:00:17 +00007574 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007575 bind_conf->bind_proc &= mask;
7576
7577 if (!bind_conf->bind_proc && nbproc == 1) {
7578 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",
7579 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7580 bind_conf->bind_proc = mask & ~(mask - 1);
7581 }
7582 else if (!bind_conf->bind_proc && nbproc > 1) {
7583 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",
7584 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7585 bind_conf->bind_proc = 0;
7586 }
7587 }
7588
Willy Tarreauff01a212009-03-15 13:46:16 +01007589 switch (curproxy->mode) {
7590 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007591 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007592 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007593 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7594 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007595 cfgerr++;
7596 }
7597
7598 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007599 Warning("config : servers will be ignored for %s '%s'.\n",
7600 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007601 break;
7602
7603 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007604 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007605 break;
7606
7607 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007608 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007609 break;
7610 }
7611
Willy Tarreauf3934b82015-08-11 11:36:45 +02007612 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7613 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7614 proxy_type_str(curproxy), curproxy->id);
7615 err_code |= ERR_WARN;
7616 }
7617
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007618 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007619 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007620 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007621 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7622 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007623 cfgerr++;
7624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007625#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007626 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007627 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7628 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007629 cfgerr++;
7630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007631#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007632 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007633 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7634 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007635 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007636 }
7637 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007638 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007639 /* If no LB algo is set in a backend, and we're not in
7640 * transparent mode, dispatch mode nor proxy mode, we
7641 * want to use balance roundrobin by default.
7642 */
7643 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7644 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007645 }
7646 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007647
Willy Tarreau1620ec32011-08-06 17:05:02 +02007648 if (curproxy->options & PR_O_DISPATCH)
7649 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7650 else if (curproxy->options & PR_O_HTTP_PROXY)
7651 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7652 else if (curproxy->options & PR_O_TRANSP)
7653 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007654
Willy Tarreau1620ec32011-08-06 17:05:02 +02007655 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7656 if (curproxy->options & PR_O_DISABLE404) {
7657 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7658 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7659 err_code |= ERR_WARN;
7660 curproxy->options &= ~PR_O_DISABLE404;
7661 }
7662 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7663 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7664 "send-state", proxy_type_str(curproxy), curproxy->id);
7665 err_code |= ERR_WARN;
7666 curproxy->options &= ~PR_O2_CHK_SNDST;
7667 }
Willy Tarreauef781042010-01-27 11:53:01 +01007668 }
7669
Simon Horman98637e52014-06-20 12:30:16 +09007670 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7671 if (!global.external_check) {
7672 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7673 curproxy->id, "option external-check");
7674 cfgerr++;
7675 }
7676 if (!curproxy->check_command) {
7677 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7678 curproxy->id, "option external-check");
7679 cfgerr++;
7680 }
7681 }
7682
Simon Horman64e34162015-02-06 11:11:57 +09007683 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007684 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7685 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007686 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7687 "'email-alert myhostname', or 'email-alert to' "
7688 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007689 "to be present).\n",
7690 proxy_type_str(curproxy), curproxy->id);
7691 err_code |= ERR_WARN;
7692 free_email_alert(curproxy);
7693 }
7694 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007695 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007696 }
7697
Simon Horman98637e52014-06-20 12:30:16 +09007698 if (curproxy->check_command) {
7699 int clear = 0;
7700 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7701 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7702 "external-check command", proxy_type_str(curproxy), curproxy->id);
7703 err_code |= ERR_WARN;
7704 clear = 1;
7705 }
7706 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007707 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007708 curproxy->id, "external-check command");
7709 cfgerr++;
7710 }
7711 if (clear) {
7712 free(curproxy->check_command);
7713 curproxy->check_command = NULL;
7714 }
7715 }
7716
7717 if (curproxy->check_path) {
7718 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7719 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7720 "external-check path", proxy_type_str(curproxy), curproxy->id);
7721 err_code |= ERR_WARN;
7722 free(curproxy->check_path);
7723 curproxy->check_path = NULL;
7724 }
7725 }
7726
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007727 /* if a default backend was specified, let's find it */
7728 if (curproxy->defbe.name) {
7729 struct proxy *target;
7730
Willy Tarreauafb39922015-05-26 12:04:09 +02007731 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007732 if (!target) {
7733 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7734 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007735 cfgerr++;
7736 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007737 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7738 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007739 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007740 } else if (target->mode != curproxy->mode &&
7741 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7742
7743 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7744 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7745 curproxy->conf.file, curproxy->conf.line,
7746 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7747 target->conf.file, target->conf.line);
7748 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007749 } else {
7750 free(curproxy->defbe.name);
7751 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007752
7753 /* Emit a warning if this proxy also has some servers */
7754 if (curproxy->srv) {
7755 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7756 curproxy->id);
7757 err_code |= ERR_WARN;
7758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007759 }
7760 }
7761
Willy Tarreau55ea7572007-06-17 19:56:27 +02007762 /* find the target proxy for 'use_backend' rules */
7763 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007764 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007765 struct logformat_node *node;
7766 char *pxname;
7767
7768 /* Try to parse the string as a log format expression. If the result
7769 * of the parsing is only one entry containing a simple string, then
7770 * it's a standard string corresponding to a static rule, thus the
7771 * parsing is cancelled and be.name is restored to be resolved.
7772 */
7773 pxname = rule->be.name;
7774 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007775 curproxy->conf.args.ctx = ARGC_UBK;
7776 curproxy->conf.args.file = rule->file;
7777 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007778 err = NULL;
7779 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7780 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7781 rule->file, rule->line, pxname, err);
7782 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007783 cfgerr++;
7784 continue;
7785 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007786 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7787
7788 if (!LIST_ISEMPTY(&rule->be.expr)) {
7789 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7790 rule->dynamic = 1;
7791 free(pxname);
7792 continue;
7793 }
7794 /* simple string: free the expression and fall back to static rule */
7795 free(node->arg);
7796 free(node);
7797 }
7798
7799 rule->dynamic = 0;
7800 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007801
Willy Tarreauafb39922015-05-26 12:04:09 +02007802 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007803 if (!target) {
7804 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7805 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007806 cfgerr++;
7807 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007808 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7809 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007810 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007811 } else if (target->mode != curproxy->mode &&
7812 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7813
7814 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7815 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7816 curproxy->conf.file, curproxy->conf.line,
7817 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7818 target->conf.file, target->conf.line);
7819 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007820 } else {
7821 free((void *)rule->be.name);
7822 rule->be.backend = target;
7823 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007824 }
7825
Willy Tarreau64ab6072014-09-16 12:17:36 +02007826 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007827 list_for_each_entry(srule, &curproxy->server_rules, list) {
7828 struct server *target = findserver(curproxy, srule->srv.name);
7829
7830 if (!target) {
7831 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7832 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7833 cfgerr++;
7834 continue;
7835 }
7836 free((void *)srule->srv.name);
7837 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007838 }
7839
Emeric Brunb982a3d2010-01-04 15:45:53 +01007840 /* find the target table for 'stick' rules */
7841 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7842 struct proxy *target;
7843
Emeric Brun1d33b292010-01-04 15:47:17 +01007844 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7845 if (mrule->flags & STK_IS_STORE)
7846 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7847
Emeric Brunb982a3d2010-01-04 15:45:53 +01007848 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007849 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007850 else
7851 target = curproxy;
7852
7853 if (!target) {
7854 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7855 curproxy->id, mrule->table.name);
7856 cfgerr++;
7857 }
7858 else if (target->table.size == 0) {
7859 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7860 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7861 cfgerr++;
7862 }
Willy Tarreau12785782012-04-27 21:37:17 +02007863 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7864 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007865 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7866 cfgerr++;
7867 }
7868 else {
7869 free((void *)mrule->table.name);
7870 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007871 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007872 }
7873 }
7874
7875 /* find the target table for 'store response' rules */
7876 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7877 struct proxy *target;
7878
Emeric Brun1d33b292010-01-04 15:47:17 +01007879 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7880
Emeric Brunb982a3d2010-01-04 15:45:53 +01007881 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007882 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007883 else
7884 target = curproxy;
7885
7886 if (!target) {
7887 Alert("Proxy '%s': unable to find store table '%s'.\n",
7888 curproxy->id, mrule->table.name);
7889 cfgerr++;
7890 }
7891 else if (target->table.size == 0) {
7892 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7893 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7894 cfgerr++;
7895 }
Willy Tarreau12785782012-04-27 21:37:17 +02007896 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7897 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007898 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7899 cfgerr++;
7900 }
7901 else {
7902 free((void *)mrule->table.name);
7903 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007904 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007905 }
7906 }
7907
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007908 /* find the target table for 'tcp-request' layer 4 rules */
7909 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7910 struct proxy *target;
7911
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007912 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007913 continue;
7914
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007915 if (trule->arg.trk_ctr.table.n)
7916 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007917 else
7918 target = curproxy;
7919
7920 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007921 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007922 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007923 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007924 cfgerr++;
7925 }
7926 else if (target->table.size == 0) {
7927 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007928 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007929 cfgerr++;
7930 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007931 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007932 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007933 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007934 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007935 cfgerr++;
7936 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007937 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007938 free(trule->arg.trk_ctr.table.n);
7939 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007940 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007941 * to pass a list of counters to track and allocate them right here using
7942 * stktable_alloc_data_type().
7943 */
7944 }
7945 }
7946
Willy Tarreau620408f2016-10-21 16:37:51 +02007947 /* find the target table for 'tcp-request' layer 5 rules */
7948 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7949 struct proxy *target;
7950
7951 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7952 continue;
7953
7954 if (trule->arg.trk_ctr.table.n)
7955 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7956 else
7957 target = curproxy;
7958
7959 if (!target) {
7960 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7961 curproxy->id, trule->arg.trk_ctr.table.n,
7962 tcp_trk_idx(trule->action));
7963 cfgerr++;
7964 }
7965 else if (target->table.size == 0) {
7966 Alert("Proxy '%s': table '%s' used but not configured.\n",
7967 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7968 cfgerr++;
7969 }
7970 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7971 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7972 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7973 tcp_trk_idx(trule->action));
7974 cfgerr++;
7975 }
7976 else {
7977 free(trule->arg.trk_ctr.table.n);
7978 trule->arg.trk_ctr.table.t = &target->table;
7979 /* Note: if we decide to enhance the track-sc syntax, we may be able
7980 * to pass a list of counters to track and allocate them right here using
7981 * stktable_alloc_data_type().
7982 */
7983 }
7984 }
7985
Willy Tarreaud1f96522010-08-03 19:34:32 +02007986 /* find the target table for 'tcp-request' layer 6 rules */
7987 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7988 struct proxy *target;
7989
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007990 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007991 continue;
7992
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007993 if (trule->arg.trk_ctr.table.n)
7994 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007995 else
7996 target = curproxy;
7997
7998 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007999 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008000 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008001 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02008002 cfgerr++;
8003 }
8004 else if (target->table.size == 0) {
8005 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008006 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008007 cfgerr++;
8008 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008009 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01008010 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008011 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008012 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01008013 cfgerr++;
8014 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008015 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008016 free(trule->arg.trk_ctr.table.n);
8017 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02008018 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02008019 * to pass a list of counters to track and allocate them right here using
8020 * stktable_alloc_data_type().
8021 */
8022 }
8023 }
8024
Baptiste Assmanne9544932015-11-03 23:31:35 +01008025 /* parse http-request capture rules to ensure id really exists */
8026 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8027 if (hrqrule->action != ACT_CUSTOM ||
8028 hrqrule->action_ptr != http_action_req_capture_by_id)
8029 continue;
8030
8031 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8032 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8033 curproxy->id, hrqrule->arg.capid.idx);
8034 cfgerr++;
8035 }
8036 }
8037
8038 /* parse http-response capture rules to ensure id really exists */
8039 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8040 if (hrqrule->action != ACT_CUSTOM ||
8041 hrqrule->action_ptr != http_action_res_capture_by_id)
8042 continue;
8043
8044 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8045 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8046 curproxy->id, hrqrule->arg.capid.idx);
8047 cfgerr++;
8048 }
8049 }
8050
Willy Tarreau09448f72014-06-25 18:12:15 +02008051 /* find the target table for 'http-request' layer 7 rules */
8052 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8053 struct proxy *target;
8054
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008055 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008056 continue;
8057
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008058 if (hrqrule->arg.trk_ctr.table.n)
8059 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008060 else
8061 target = curproxy;
8062
8063 if (!target) {
8064 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008065 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008066 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008067 cfgerr++;
8068 }
8069 else if (target->table.size == 0) {
8070 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008071 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008072 cfgerr++;
8073 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008074 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008075 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008076 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008077 http_trk_idx(hrqrule->action));
8078 cfgerr++;
8079 }
8080 else {
8081 free(hrqrule->arg.trk_ctr.table.n);
8082 hrqrule->arg.trk_ctr.table.t = &target->table;
8083 /* Note: if we decide to enhance the track-sc syntax, we may be able
8084 * to pass a list of counters to track and allocate them right here using
8085 * stktable_alloc_data_type().
8086 */
8087 }
8088 }
8089
8090 /* find the target table for 'http-response' layer 7 rules */
8091 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8092 struct proxy *target;
8093
8094 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8095 continue;
8096
8097 if (hrqrule->arg.trk_ctr.table.n)
8098 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8099 else
8100 target = curproxy;
8101
8102 if (!target) {
8103 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8104 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8105 http_trk_idx(hrqrule->action));
8106 cfgerr++;
8107 }
8108 else if (target->table.size == 0) {
8109 Alert("Proxy '%s': table '%s' used but not configured.\n",
8110 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8111 cfgerr++;
8112 }
8113 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8114 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8115 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8116 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008117 cfgerr++;
8118 }
8119 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008120 free(hrqrule->arg.trk_ctr.table.n);
8121 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008122 /* Note: if we decide to enhance the track-sc syntax, we may be able
8123 * to pass a list of counters to track and allocate them right here using
8124 * stktable_alloc_data_type().
8125 */
8126 }
8127 }
8128
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008129 /* move any "block" rules at the beginning of the http-request rules */
8130 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8131 /* insert block_rules into http_req_rules at the beginning */
8132 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8133 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8134 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8135 curproxy->http_req_rules.n = curproxy->block_rules.n;
8136 LIST_INIT(&curproxy->block_rules);
8137 }
8138
Emeric Brun32da3c42010-09-23 18:39:19 +02008139 if (curproxy->table.peers.name) {
8140 struct peers *curpeers = peers;
8141
8142 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8143 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8144 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008145 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008146 break;
8147 }
8148 }
8149
8150 if (!curpeers) {
8151 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8152 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008153 free((void *)curproxy->table.peers.name);
8154 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008155 cfgerr++;
8156 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008157 else if (curpeers->state == PR_STSTOPPED) {
8158 /* silently disable this peers section */
8159 curproxy->table.peers.p = NULL;
8160 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008161 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008162 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8163 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008164 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008165 cfgerr++;
8166 }
8167 }
8168
Simon Horman9dc49962015-01-30 11:22:59 +09008169
8170 if (curproxy->email_alert.mailers.name) {
8171 struct mailers *curmailers = mailers;
8172
8173 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8174 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8175 free(curproxy->email_alert.mailers.name);
8176 curproxy->email_alert.mailers.m = curmailers;
8177 curmailers->users++;
8178 break;
8179 }
8180 }
8181
8182 if (!curmailers) {
8183 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8184 curproxy->id, curproxy->email_alert.mailers.name);
8185 free_email_alert(curproxy);
8186 cfgerr++;
8187 }
8188 }
8189
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008190 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008191 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008192 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8193 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8194 "proxy", curproxy->id);
8195 cfgerr++;
8196 goto out_uri_auth_compat;
8197 }
8198
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008199 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008200 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008201 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008202 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008203
Willy Tarreau95fa4692010-02-01 13:05:50 +01008204 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8205 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008206
8207 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008208 uri_auth_compat_req[i++] = "realm";
8209 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8210 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008211
Willy Tarreau95fa4692010-02-01 13:05:50 +01008212 uri_auth_compat_req[i++] = "unless";
8213 uri_auth_compat_req[i++] = "{";
8214 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8215 uri_auth_compat_req[i++] = "}";
8216 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008217
Willy Tarreauff011f22011-01-06 17:51:27 +01008218 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8219 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008220 cfgerr++;
8221 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008222 }
8223
Willy Tarreauff011f22011-01-06 17:51:27 +01008224 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008225
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008226 if (curproxy->uri_auth->auth_realm) {
8227 free(curproxy->uri_auth->auth_realm);
8228 curproxy->uri_auth->auth_realm = NULL;
8229 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008230
8231 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008232 }
8233out_uri_auth_compat:
8234
Dragan Dosen43885c72015-10-01 13:18:13 +02008235 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008236 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008237 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8238 if (!curproxy->conf.logformat_sd_string) {
8239 /* set the default logformat_sd_string */
8240 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8241 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008242 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008243 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008244 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008245
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008246 /* compile the log format */
8247 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008248 if (curproxy->conf.logformat_string != default_http_log_format &&
8249 curproxy->conf.logformat_string != default_tcp_log_format &&
8250 curproxy->conf.logformat_string != clf_http_log_format)
8251 free(curproxy->conf.logformat_string);
8252 curproxy->conf.logformat_string = NULL;
8253 free(curproxy->conf.lfs_file);
8254 curproxy->conf.lfs_file = NULL;
8255 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008256
8257 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8258 free(curproxy->conf.logformat_sd_string);
8259 curproxy->conf.logformat_sd_string = NULL;
8260 free(curproxy->conf.lfsd_file);
8261 curproxy->conf.lfsd_file = NULL;
8262 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008263 }
8264
Willy Tarreau62a61232013-04-12 18:13:46 +02008265 if (curproxy->conf.logformat_string) {
8266 curproxy->conf.args.ctx = ARGC_LOG;
8267 curproxy->conf.args.file = curproxy->conf.lfs_file;
8268 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008269 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008270 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008271 SMP_VAL_FE_LOG_END, &err)) {
8272 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8273 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8274 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008275 cfgerr++;
8276 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008277 curproxy->conf.args.file = NULL;
8278 curproxy->conf.args.line = 0;
8279 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008280
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008281 if (curproxy->conf.logformat_sd_string) {
8282 curproxy->conf.args.ctx = ARGC_LOGSD;
8283 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8284 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008285 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008286 if (!parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008287 SMP_VAL_FE_LOG_END, &err)) {
8288 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8289 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8290 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008291 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008292 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8293 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8294 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8295 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008296 cfgerr++;
8297 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008298 curproxy->conf.args.file = NULL;
8299 curproxy->conf.args.line = 0;
8300 }
8301
Willy Tarreau62a61232013-04-12 18:13:46 +02008302 if (curproxy->conf.uniqueid_format_string) {
8303 curproxy->conf.args.ctx = ARGC_UIF;
8304 curproxy->conf.args.file = curproxy->conf.uif_file;
8305 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008306 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008307 if (!parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008308 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8309 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8310 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8311 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008312 cfgerr++;
8313 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008314 curproxy->conf.args.file = NULL;
8315 curproxy->conf.args.line = 0;
8316 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008317
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008318 /* only now we can check if some args remain unresolved.
8319 * This must be done after the users and groups resolution.
8320 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008321 cfgerr += smp_resolve_args(curproxy);
8322 if (!cfgerr)
8323 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008324
Willy Tarreau2738a142006-07-08 17:28:09 +02008325 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008326 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008327 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008328 (!curproxy->timeout.connect ||
8329 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008330 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008331 " | While not properly invalid, you will certainly encounter various problems\n"
8332 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008333 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008334 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008335 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008336 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008337
Willy Tarreau1fa31262007-12-03 00:36:16 +01008338 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8339 * We must still support older configurations, so let's find out whether those
8340 * parameters have been set or must be copied from contimeouts.
8341 */
8342 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008343 if (!curproxy->timeout.tarpit ||
8344 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008345 /* tarpit timeout not set. We search in the following order:
8346 * default.tarpit, curr.connect, default.connect.
8347 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008348 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008349 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008350 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008351 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008352 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008353 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008354 }
8355 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008356 (!curproxy->timeout.queue ||
8357 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008358 /* queue timeout not set. We search in the following order:
8359 * default.queue, curr.connect, default.connect.
8360 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008361 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008362 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008363 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008364 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008365 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008366 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008367 }
8368 }
8369
Willy Tarreau1620ec32011-08-06 17:05:02 +02008370 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008371 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008372 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008373 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008374 }
8375
Willy Tarreau215663d2014-06-13 18:30:23 +02008376 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8377 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8378 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8379 proxy_type_str(curproxy), curproxy->id);
8380 err_code |= ERR_WARN;
8381 }
8382
Willy Tarreau193b8c62012-11-22 00:17:38 +01008383 /* ensure that cookie capture length is not too large */
8384 if (curproxy->capture_len >= global.tune.cookie_len) {
8385 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8386 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8387 err_code |= ERR_WARN;
8388 curproxy->capture_len = global.tune.cookie_len - 1;
8389 }
8390
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008391 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008392 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008393 curproxy->req_cap_pool = create_pool("ptrcap",
8394 curproxy->nb_req_cap * sizeof(char *),
8395 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008396 }
8397
8398 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008399 curproxy->rsp_cap_pool = create_pool("ptrcap",
8400 curproxy->nb_rsp_cap * sizeof(char *),
8401 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008402 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008403
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008404 switch (curproxy->load_server_state_from_file) {
8405 case PR_SRV_STATE_FILE_UNSPEC:
8406 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8407 break;
8408 case PR_SRV_STATE_FILE_GLOBAL:
8409 if (!global.server_state_file) {
8410 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",
8411 curproxy->id);
8412 err_code |= ERR_WARN;
8413 }
8414 break;
8415 }
8416
Willy Tarreaubaaee002006-06-26 02:48:02 +02008417 /* first, we will invert the servers list order */
8418 newsrv = NULL;
8419 while (curproxy->srv) {
8420 struct server *next;
8421
8422 next = curproxy->srv->next;
8423 curproxy->srv->next = newsrv;
8424 newsrv = curproxy->srv;
8425 if (!next)
8426 break;
8427 curproxy->srv = next;
8428 }
8429
Willy Tarreau17edc812014-01-03 12:14:34 +01008430 /* Check that no server name conflicts. This causes trouble in the stats.
8431 * We only emit a warning for the first conflict affecting each server,
8432 * in order to avoid combinatory explosion if all servers have the same
8433 * name. We do that only for servers which do not have an explicit ID,
8434 * because these IDs were made also for distinguishing them and we don't
8435 * want to annoy people who correctly manage them.
8436 */
8437 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8438 struct server *other_srv;
8439
8440 if (newsrv->puid)
8441 continue;
8442
8443 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8444 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8445 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8446 newsrv->conf.file, newsrv->conf.line,
8447 proxy_type_str(curproxy), curproxy->id,
8448 newsrv->id, other_srv->conf.line);
8449 break;
8450 }
8451 }
8452 }
8453
Willy Tarreaudd701652010-05-25 23:03:02 +02008454 /* assign automatic UIDs to servers which don't have one yet */
8455 next_id = 1;
8456 newsrv = curproxy->srv;
8457 while (newsrv != NULL) {
8458 if (!newsrv->puid) {
8459 /* server ID not set, use automatic numbering with first
8460 * spare entry starting with next_svid.
8461 */
8462 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8463 newsrv->conf.id.key = newsrv->puid = next_id;
8464 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8465 }
8466 next_id++;
8467 newsrv = newsrv->next;
8468 }
8469
Willy Tarreau20697042007-11-15 23:26:18 +01008470 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008471 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008472
Willy Tarreau62c3be22012-01-20 13:12:32 +01008473 /*
8474 * If this server supports a maxconn parameter, it needs a dedicated
8475 * tasks to fill the emptied slots when a connection leaves.
8476 * Also, resolve deferred tracking dependency if needed.
8477 */
8478 newsrv = curproxy->srv;
8479 while (newsrv != NULL) {
8480 if (newsrv->minconn > newsrv->maxconn) {
8481 /* Only 'minconn' was specified, or it was higher than or equal
8482 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8483 * this will avoid further useless expensive computations.
8484 */
8485 newsrv->maxconn = newsrv->minconn;
8486 } else if (newsrv->maxconn && !newsrv->minconn) {
8487 /* minconn was not specified, so we set it to maxconn */
8488 newsrv->minconn = newsrv->maxconn;
8489 }
8490
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008491#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008492 if (newsrv->use_ssl || newsrv->check.use_ssl)
8493 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008494#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008495
Willy Tarreau2f075e92013-12-03 11:11:34 +01008496 /* set the check type on the server */
8497 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8498
Willy Tarreau62c3be22012-01-20 13:12:32 +01008499 if (newsrv->trackit) {
8500 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008501 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008502 char *pname, *sname;
8503
8504 pname = newsrv->trackit;
8505 sname = strrchr(pname, '/');
8506
8507 if (sname)
8508 *sname++ = '\0';
8509 else {
8510 sname = pname;
8511 pname = NULL;
8512 }
8513
8514 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008515 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008516 if (!px) {
8517 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8518 proxy_type_str(curproxy), curproxy->id,
8519 newsrv->id, pname);
8520 cfgerr++;
8521 goto next_srv;
8522 }
8523 } else
8524 px = curproxy;
8525
8526 srv = findserver(px, sname);
8527 if (!srv) {
8528 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8529 proxy_type_str(curproxy), curproxy->id,
8530 newsrv->id, sname);
8531 cfgerr++;
8532 goto next_srv;
8533 }
8534
Willy Tarreau32091232014-05-16 13:52:00 +02008535 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8536 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8537 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008538 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008539 "tracking as it does not have any check nor agent enabled.\n",
8540 proxy_type_str(curproxy), curproxy->id,
8541 newsrv->id, px->id, srv->id);
8542 cfgerr++;
8543 goto next_srv;
8544 }
8545
8546 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8547
8548 if (loop) {
8549 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8550 "belongs to a tracking chain looping back to %s/%s.\n",
8551 proxy_type_str(curproxy), curproxy->id,
8552 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008553 cfgerr++;
8554 goto next_srv;
8555 }
8556
8557 if (curproxy != px &&
8558 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8559 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8560 "tracking: disable-on-404 option inconsistency.\n",
8561 proxy_type_str(curproxy), curproxy->id,
8562 newsrv->id, px->id, srv->id);
8563 cfgerr++;
8564 goto next_srv;
8565 }
8566
Willy Tarreau62c3be22012-01-20 13:12:32 +01008567 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008568 newsrv->tracknext = srv->trackers;
8569 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008570
8571 free(newsrv->trackit);
8572 newsrv->trackit = NULL;
8573 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008574
8575 /*
8576 * resolve server's resolvers name and update the resolvers pointer
8577 * accordingly
8578 */
8579 if (newsrv->resolvers_id) {
8580 struct dns_resolvers *curr_resolvers;
8581 int found;
8582
8583 found = 0;
8584 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8585 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8586 found = 1;
8587 break;
8588 }
8589 }
8590
8591 if (!found) {
8592 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8593 proxy_type_str(curproxy), curproxy->id,
8594 newsrv->id, newsrv->resolvers_id);
8595 cfgerr++;
8596 } else {
8597 free(newsrv->resolvers_id);
8598 newsrv->resolvers_id = NULL;
8599 if (newsrv->resolution)
8600 newsrv->resolution->resolvers = curr_resolvers;
8601 }
8602 }
8603 else {
8604 /* if no resolvers section associated to this server
8605 * we can clean up the associated resolution structure
8606 */
8607 if (newsrv->resolution) {
8608 free(newsrv->resolution->hostname_dn);
8609 newsrv->resolution->hostname_dn = NULL;
8610 free(newsrv->resolution);
8611 newsrv->resolution = NULL;
8612 }
8613 }
8614
Willy Tarreau62c3be22012-01-20 13:12:32 +01008615 next_srv:
8616 newsrv = newsrv->next;
8617 }
8618
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008619 /* We have to initialize the server lookup mechanism depending
8620 * on what LB algorithm was choosen.
8621 */
8622
8623 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8624 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8625 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008626 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8627 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8628 init_server_map(curproxy);
8629 } else {
8630 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8631 fwrr_init_server_groups(curproxy);
8632 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008633 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008634
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008635 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008636 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8637 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8638 fwlc_init_server_tree(curproxy);
8639 } else {
8640 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8641 fas_init_server_tree(curproxy);
8642 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008643 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008644
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008645 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008646 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8647 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8648 chash_init_server_tree(curproxy);
8649 } else {
8650 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8651 init_server_map(curproxy);
8652 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008653 break;
8654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008655
8656 if (curproxy->options & PR_O_LOGASAP)
8657 curproxy->to_log &= ~LW_BYTES;
8658
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008659 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008660 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8661 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008662 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8663 proxy_type_str(curproxy), curproxy->id);
8664 err_code |= ERR_WARN;
8665 }
8666
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008667 if (curproxy->mode != PR_MODE_HTTP) {
8668 int optnum;
8669
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008670 if (curproxy->uri_auth) {
8671 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8672 proxy_type_str(curproxy), curproxy->id);
8673 err_code |= ERR_WARN;
8674 curproxy->uri_auth = NULL;
8675 }
8676
Willy Tarreau87cf5142011-08-19 22:57:24 +02008677 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008678 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8679 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8680 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008681 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008682 }
8683
8684 if (curproxy->options & PR_O_ORGTO) {
8685 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8686 "originalto", proxy_type_str(curproxy), curproxy->id);
8687 err_code |= ERR_WARN;
8688 curproxy->options &= ~PR_O_ORGTO;
8689 }
8690
8691 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8692 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8693 (curproxy->cap & cfg_opts[optnum].cap) &&
8694 (curproxy->options & cfg_opts[optnum].val)) {
8695 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8696 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8697 err_code |= ERR_WARN;
8698 curproxy->options &= ~cfg_opts[optnum].val;
8699 }
8700 }
8701
8702 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8703 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8704 (curproxy->cap & cfg_opts2[optnum].cap) &&
8705 (curproxy->options2 & cfg_opts2[optnum].val)) {
8706 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8707 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8708 err_code |= ERR_WARN;
8709 curproxy->options2 &= ~cfg_opts2[optnum].val;
8710 }
8711 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008712
Willy Tarreau29fbe512015-08-20 19:35:14 +02008713#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008714 if (curproxy->conn_src.bind_hdr_occ) {
8715 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008716 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008717 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008718 err_code |= ERR_WARN;
8719 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008720#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008721 }
8722
Willy Tarreaubaaee002006-06-26 02:48:02 +02008723 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008724 * ensure that we're not cross-dressing a TCP server into HTTP.
8725 */
8726 newsrv = curproxy->srv;
8727 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008728 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008729 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8730 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008731 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008732 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008733
Willy Tarreau0cec3312011-10-31 13:49:26 +01008734 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8735 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8736 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8737 err_code |= ERR_WARN;
8738 }
8739
Willy Tarreauc93cd162014-05-13 15:54:22 +02008740 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008741 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8742 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8743 err_code |= ERR_WARN;
8744 }
8745
Willy Tarreau29fbe512015-08-20 19:35:14 +02008746#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008747 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8748 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008749 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 +01008750 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008751 err_code |= ERR_WARN;
8752 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008753#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008754 newsrv = newsrv->next;
8755 }
8756
Willy Tarreaue42bd962014-09-16 16:21:19 +02008757 /* check if we have a frontend with "tcp-request content" looking at L7
8758 * with no inspect-delay
8759 */
8760 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8761 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008762 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008763 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008764 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008765 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008766 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008767 break;
8768 }
8769
8770 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8771 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8772 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8773 " This means that these rules will randomly find their contents. This can be fixed by"
8774 " setting the tcp-request inspect-delay.\n",
8775 proxy_type_str(curproxy), curproxy->id);
8776 err_code |= ERR_WARN;
8777 }
8778 }
8779
Christopher Fauletd7c91962015-04-30 11:48:27 +02008780 /* Check filter configuration, if any */
8781 cfgerr += flt_check(curproxy);
8782
Willy Tarreauc1a21672009-08-16 22:37:44 +02008783 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008784 if (!curproxy->accept)
8785 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008786
Willy Tarreauc1a21672009-08-16 22:37:44 +02008787 if (curproxy->tcp_req.inspect_delay ||
8788 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008789 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008790
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008791 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008792 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008793 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008794 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008795
8796 /* both TCP and HTTP must check switching rules */
8797 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008798
8799 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008800 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008801 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8802 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008803 if (curproxy->mode == PR_MODE_HTTP) {
8804 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8805 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8806 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008807 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008808 }
8809
8810 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008811 if (curproxy->tcp_req.inspect_delay ||
8812 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8813 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8814
Emeric Brun97679e72010-09-23 17:56:44 +02008815 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8816 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8817
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008818 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008819 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008820 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008821 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008822
8823 /* If the backend does requires RDP cookie persistence, we have to
8824 * enable the corresponding analyser.
8825 */
8826 if (curproxy->options2 & PR_O2_RDPC_PRST)
8827 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008828
8829 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008830 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008831 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8832 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008833 if (curproxy->mode == PR_MODE_HTTP) {
8834 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8835 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8836 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008837 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008838 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008839 }
8840
8841 /***********************************************************/
8842 /* At this point, target names have already been resolved. */
8843 /***********************************************************/
8844
8845 /* Check multi-process mode compatibility */
8846
8847 if (global.nbproc > 1 && global.stats_fe) {
8848 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8849 unsigned long mask;
8850
8851 mask = nbits(global.nbproc);
8852 if (global.stats_fe->bind_proc)
8853 mask &= global.stats_fe->bind_proc;
8854
8855 if (bind_conf->bind_proc)
8856 mask &= bind_conf->bind_proc;
8857
8858 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008859 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008860 break;
8861 }
8862 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8863 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");
8864 }
8865 }
8866
8867 /* Make each frontend inherit bind-process from its listeners when not specified. */
8868 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8869 if (curproxy->bind_proc)
8870 continue;
8871
8872 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8873 unsigned long mask;
8874
Willy Tarreaue428b082015-05-04 21:57:58 +02008875 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008876 curproxy->bind_proc |= mask;
8877 }
8878
8879 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008880 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008881 }
8882
8883 if (global.stats_fe) {
8884 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8885 unsigned long mask;
8886
Cyril Bonté06181952016-02-24 00:14:54 +01008887 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008888 global.stats_fe->bind_proc |= mask;
8889 }
8890 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008891 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008892 }
8893
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008894 /* propagate bindings from frontends to backends. Don't do it if there
8895 * are any fatal errors as we must not call it with unresolved proxies.
8896 */
8897 if (!cfgerr) {
8898 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8899 if (curproxy->cap & PR_CAP_FE)
8900 propagate_processes(curproxy, NULL);
8901 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008902 }
8903
8904 /* Bind each unbound backend to all processes when not specified. */
8905 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8906 if (curproxy->bind_proc)
8907 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008908 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008909 }
8910
8911 /*******************************************************/
8912 /* At this step, all proxies have a non-null bind_proc */
8913 /*******************************************************/
8914
8915 /* perform the final checks before creating tasks */
8916
8917 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8918 struct listener *listener;
8919 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008920
Emeric Brunc52962f2012-11-15 18:28:02 +01008921#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008922 /* Configure SSL for each bind line.
8923 * Note: if configuration fails at some point, the ->ctx member
8924 * remains NULL so that listeners can later detach.
8925 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008926 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008927 int alloc_ctx;
8928
Emeric Brunc52962f2012-11-15 18:28:02 +01008929 if (!bind_conf->is_ssl) {
8930 if (bind_conf->default_ctx) {
8931 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8932 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8933 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008934 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008935 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008936 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008937 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008938 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008939 cfgerr++;
8940 continue;
8941 }
8942
Emeric Brun8dc60392014-05-09 13:52:00 +02008943 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008944 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008945 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8946 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");
8947 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008948 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008949 cfgerr++;
8950 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008951 }
8952
Emeric Brunfc0421f2012-09-07 17:30:07 +02008953 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008954 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008955
8956 /* initialize CA variables if the certificates generation is enabled */
8957 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008958 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008959#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008960
Willy Tarreaue6b98942007-10-29 01:09:36 +01008961 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008962 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008963 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008964 int nbproc;
8965
8966 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008967 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008968 nbits(global.nbproc));
8969
8970 if (!nbproc) /* no intersection between listener and frontend */
8971 nbproc = 1;
8972
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008973 if (!listener->luid) {
8974 /* listener ID not set, use automatic numbering with first
8975 * spare entry starting with next_luid.
8976 */
8977 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8978 listener->conf.id.key = listener->luid = next_id;
8979 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008980 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008981 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008982
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008983 /* enable separate counters */
8984 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008985 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008986 if (!listener->name)
8987 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008988 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008989
Willy Tarreaue6b98942007-10-29 01:09:36 +01008990 if (curproxy->options & PR_O_TCP_NOLING)
8991 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008992 if (!listener->maxconn)
8993 listener->maxconn = curproxy->maxconn;
8994 if (!listener->backlog)
8995 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008996 if (!listener->maxaccept)
8997 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8998
8999 /* we want to have an optimal behaviour on single process mode to
9000 * maximize the work at once, but in multi-process we want to keep
9001 * some fairness between processes, so we target half of the max
9002 * number of events to be balanced over all the processes the proxy
9003 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9004 * used to disable the limit.
9005 */
9006 if (listener->maxaccept > 0) {
9007 if (nbproc > 1)
9008 listener->maxaccept = (listener->maxaccept + 1) / 2;
9009 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9010 }
9011
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009012 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02009013 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009014 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009015 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009016
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009017 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009018 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009019
Willy Tarreau620408f2016-10-21 16:37:51 +02009020 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9021 listener->options |= LI_O_TCP_L5_RULES;
9022
Willy Tarreaude3041d2010-05-31 10:56:17 +02009023 if (curproxy->mon_mask.s_addr)
9024 listener->options |= LI_O_CHK_MONNET;
9025
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009026 /* smart accept mode is automatic in HTTP mode */
9027 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009028 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009029 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9030 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009031 }
9032
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009033 /* Release unused SSL configs */
9034 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
9035 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009036 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009037#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02009038 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009039 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009040 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02009041 free(bind_conf->ca_sign_file);
9042 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009043 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02009044 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009045 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009046 if(bind_conf->keys_ref) {
9047 free(bind_conf->keys_ref->filename);
9048 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02009049 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009050 free(bind_conf->keys_ref);
9051 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009052#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009053 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009054
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009055 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009056 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009057 int count, maxproc = 0;
9058
9059 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009060 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009061 if (count > maxproc)
9062 maxproc = count;
9063 }
9064 /* backends have 0, frontends have 1 or more */
9065 if (maxproc != 1)
9066 Warning("Proxy '%s': in multi-process mode, stats will be"
9067 " limited to process assigned to the current request.\n",
9068 curproxy->id);
9069
Willy Tarreau102df612014-05-07 23:56:38 +02009070 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9071 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9072 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009073 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009074 }
Willy Tarreau102df612014-05-07 23:56:38 +02009075 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9076 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9077 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009078 }
9079 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009080
9081 /* create the task associated with the proxy */
9082 curproxy->task = task_new();
9083 if (curproxy->task) {
9084 curproxy->task->context = curproxy;
9085 curproxy->task->process = manage_proxy;
9086 /* no need to queue, it will be done automatically if some
9087 * listener gets limited.
9088 */
9089 curproxy->task->expire = TICK_ETERNITY;
9090 } else {
9091 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9092 curproxy->id);
9093 cfgerr++;
9094 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009095 }
9096
Willy Tarreaufbb78422011-06-05 15:38:35 +02009097 /* automatically compute fullconn if not set. We must not do it in the
9098 * loop above because cross-references are not yet fully resolved.
9099 */
9100 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9101 /* If <fullconn> is not set, let's set it to 10% of the sum of
9102 * the possible incoming frontend's maxconns.
9103 */
9104 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9105 struct proxy *fe;
9106 int total = 0;
9107
9108 /* sum up the number of maxconns of frontends which
9109 * reference this backend at least once or which are
9110 * the same one ('listen').
9111 */
9112 for (fe = proxy; fe; fe = fe->next) {
9113 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009114 int found = 0;
9115
9116 if (!(fe->cap & PR_CAP_FE))
9117 continue;
9118
9119 if (fe == curproxy) /* we're on a "listen" instance */
9120 found = 1;
9121
9122 if (fe->defbe.be == curproxy) /* "default_backend" */
9123 found = 1;
9124
9125 /* check if a "use_backend" rule matches */
9126 if (!found) {
9127 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009128 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009129 found = 1;
9130 break;
9131 }
9132 }
9133 }
9134
Willy Tarreaufbb78422011-06-05 15:38:35 +02009135 /* now we've checked all possible ways to reference a backend
9136 * from a frontend.
9137 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009138 if (!found)
9139 continue;
9140 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009141 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009142 /* we have the sum of the maxconns in <total>. We only
9143 * keep 10% of that sum to set the default fullconn, with
9144 * a hard minimum of 1 (to avoid a divide by zero).
9145 */
9146 curproxy->fullconn = (total + 9) / 10;
9147 if (!curproxy->fullconn)
9148 curproxy->fullconn = 1;
9149 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009150 }
9151
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009152 /*
9153 * Recount currently required checks.
9154 */
9155
9156 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9157 int optnum;
9158
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009159 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9160 if (curproxy->options & cfg_opts[optnum].val)
9161 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009162
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009163 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9164 if (curproxy->options2 & cfg_opts2[optnum].val)
9165 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009166 }
9167
Willy Tarreau0fca4832015-05-01 19:12:05 +02009168 /* compute the required process bindings for the peers */
9169 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9170 if (curproxy->table.peers.p)
9171 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9172
Willy Tarreau122541c2011-09-07 21:24:49 +02009173 if (peers) {
9174 struct peers *curpeers = peers, **last;
9175 struct peer *p, *pb;
9176
Willy Tarreau1e273012015-05-01 19:15:17 +02009177 /* Remove all peers sections which don't have a valid listener,
9178 * which are not used by any table, or which are bound to more
9179 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009180 */
9181 last = &peers;
9182 while (*last) {
9183 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009184
9185 if (curpeers->state == PR_STSTOPPED) {
9186 /* the "disabled" keyword was present */
9187 if (curpeers->peers_fe)
9188 stop_proxy(curpeers->peers_fe);
9189 curpeers->peers_fe = NULL;
9190 }
9191 else if (!curpeers->peers_fe) {
9192 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9193 curpeers->id, localpeer);
9194 }
David Carliere6c39412015-07-02 07:00:17 +00009195 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009196 /* either it's totally stopped or too much used */
9197 if (curpeers->peers_fe->bind_proc) {
9198 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009199 "running in different processes (%d different ones). "
9200 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009201 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009202 cfgerr++;
9203 }
9204 stop_proxy(curpeers->peers_fe);
9205 curpeers->peers_fe = NULL;
9206 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009207 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009208 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009209 last = &curpeers->next;
9210 continue;
9211 }
9212
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009213 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009214 p = curpeers->remote;
9215 while (p) {
9216 pb = p->next;
9217 free(p->id);
9218 free(p);
9219 p = pb;
9220 }
9221
9222 /* Destroy and unlink this curpeers section.
9223 * Note: curpeers is backed up into *last.
9224 */
9225 free(curpeers->id);
9226 curpeers = curpeers->next;
9227 free(*last);
9228 *last = curpeers;
9229 }
9230 }
9231
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009232 /* initialize stick-tables on backend capable proxies. This must not
9233 * be done earlier because the data size may be discovered while parsing
9234 * other proxies.
9235 */
9236 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9237 if (curproxy->state == PR_STSTOPPED)
9238 continue;
9239
9240 if (!stktable_init(&curproxy->table)) {
9241 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9242 cfgerr++;
9243 }
9244 }
9245
Simon Horman0d16a402015-01-30 11:22:58 +09009246 if (mailers) {
9247 struct mailers *curmailers = mailers, **last;
9248 struct mailer *m, *mb;
9249
9250 /* Remove all mailers sections which don't have a valid listener.
9251 * This can happen when a mailers section is never referenced.
9252 */
9253 last = &mailers;
9254 while (*last) {
9255 curmailers = *last;
9256 if (curmailers->users) {
9257 last = &curmailers->next;
9258 continue;
9259 }
9260
9261 Warning("Removing incomplete section 'mailers %s'.\n",
9262 curmailers->id);
9263
9264 m = curmailers->mailer_list;
9265 while (m) {
9266 mb = m->next;
9267 free(m->id);
9268 free(m);
9269 m = mb;
9270 }
9271
9272 /* Destroy and unlink this curmailers section.
9273 * Note: curmailers is backed up into *last.
9274 */
9275 free(curmailers->id);
9276 curmailers = curmailers->next;
9277 free(*last);
9278 *last = curmailers;
9279 }
9280 }
9281
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009282 /* Update server_state_file_name to backend name if backend is supposed to use
9283 * a server-state file locally defined and none has been provided */
9284 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9285 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9286 curproxy->server_state_file_name == NULL)
9287 curproxy->server_state_file_name = strdup(curproxy->id);
9288 }
9289
Willy Tarreau34eb6712011-10-24 18:15:04 +02009290 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009291 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009292 MEM_F_SHARED);
9293
Willy Tarreaubb925012009-07-23 13:36:36 +02009294 if (cfgerr > 0)
9295 err_code |= ERR_ALERT | ERR_FATAL;
9296 out:
9297 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009298}
9299
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009300/*
9301 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9302 * parsing sessions.
9303 */
9304void cfg_register_keywords(struct cfg_kw_list *kwl)
9305{
9306 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9307}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009308
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009309/*
9310 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9311 */
9312void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9313{
9314 LIST_DEL(&kwl->list);
9315 LIST_INIT(&kwl->list);
9316}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009317
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009318/* this function register new section in the haproxy configuration file.
9319 * <section_name> is the name of this new section and <section_parser>
9320 * is the called parser. If two section declaration have the same name,
9321 * only the first declared is used.
9322 */
9323int cfg_register_section(char *section_name,
9324 int (*section_parser)(const char *, int, char **, int))
9325{
9326 struct cfg_section *cs;
9327
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009328 list_for_each_entry(cs, &sections, list) {
9329 if (strcmp(cs->section_name, section_name) == 0) {
9330 Alert("register section '%s': already registered.\n", section_name);
9331 return 0;
9332 }
9333 }
9334
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009335 cs = calloc(1, sizeof(*cs));
9336 if (!cs) {
9337 Alert("register section '%s': out of memory.\n", section_name);
9338 return 0;
9339 }
9340
9341 cs->section_name = section_name;
9342 cs->section_parser = section_parser;
9343
9344 LIST_ADDQ(&sections, &cs->list);
9345
9346 return 1;
9347}
9348
Willy Tarreaubaaee002006-06-26 02:48:02 +02009349/*
David Carlier845efb52015-09-25 11:49:18 +01009350 * free all config section entries
9351 */
9352void cfg_unregister_sections(void)
9353{
9354 struct cfg_section *cs, *ics;
9355
9356 list_for_each_entry_safe(cs, ics, &sections, list) {
9357 LIST_DEL(&cs->list);
9358 free(cs);
9359 }
9360}
9361
Christopher Faulet7110b402016-10-26 11:09:44 +02009362void cfg_backup_sections(struct list *backup_sections)
9363{
9364 struct cfg_section *cs, *ics;
9365
9366 list_for_each_entry_safe(cs, ics, &sections, list) {
9367 LIST_DEL(&cs->list);
9368 LIST_ADDQ(backup_sections, &cs->list);
9369 }
9370}
9371
9372void cfg_restore_sections(struct list *backup_sections)
9373{
9374 struct cfg_section *cs, *ics;
9375
9376 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9377 LIST_DEL(&cs->list);
9378 LIST_ADDQ(&sections, &cs->list);
9379 }
9380}
9381
Willy Tarreau659fbf02016-05-26 17:55:28 +02009382__attribute__((constructor))
9383static void cfgparse_init(void)
9384{
9385 /* Register internal sections */
9386 cfg_register_section("listen", cfg_parse_listen);
9387 cfg_register_section("frontend", cfg_parse_listen);
9388 cfg_register_section("backend", cfg_parse_listen);
9389 cfg_register_section("defaults", cfg_parse_listen);
9390 cfg_register_section("global", cfg_parse_global);
9391 cfg_register_section("userlist", cfg_parse_users);
9392 cfg_register_section("peers", cfg_parse_peers);
9393 cfg_register_section("mailers", cfg_parse_mailers);
9394 cfg_register_section("namespace_list", cfg_parse_netns);
9395 cfg_register_section("resolvers", cfg_parse_resolvers);
9396}
9397
David Carlier845efb52015-09-25 11:49:18 +01009398/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009399 * Local variables:
9400 * c-indent-level: 8
9401 * c-basic-offset: 8
9402 * End:
9403 */