blob: fbd7364662124bad36194b6bc863b49271568ca5 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
William Lallemand9ed62032016-11-21 17:49:11 +010062#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020063#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020064#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020065#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020066#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010067#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020068#include <proto/lb_fwlc.h>
69#include <proto/lb_fwrr.h>
70#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020071#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010074#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020075#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020083#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020084#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010085#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
Emeric Brunfc0421f2012-09-07 17:30:07 +020087#ifdef USE_OPENSSL
88#include <types/ssl_sock.h>
89#include <proto/ssl_sock.h>
90#include <proto/shctx.h>
91#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020092
Willy Tarreauf3c69202006-07-09 16:42:34 +020093/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
94 * ssl-hello-chk option to ensure that the remote server speaks SSL.
95 *
96 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
97 */
98const char sslv3_client_hello_pkt[] = {
99 "\x16" /* ContentType : 0x16 = Hanshake */
100 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
101 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
102 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
103 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
104 "\x03\x00" /* Hello Version : 0x0300 = v3 */
105 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
106 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
107 "\x00" /* Session ID length : empty (no session ID) */
108 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
109 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
110 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
111 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
112 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
113 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
114 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
115 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
116 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
117 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
118 "\x00\x38" "\x00\x39" "\x00\x3A"
119 "\x01" /* Compression Length : 0x01 = 1 byte for types */
120 "\x00" /* Compression Type : 0x00 = NULL compression */
121};
122
Willy Tarreau3842f002009-06-14 11:39:52 +0200123/* various keyword modifiers */
124enum kw_mod {
125 KWM_STD = 0, /* normal */
126 KWM_NO, /* "no" prefixed before the keyword */
127 KWM_DEF, /* "default" prefixed before the keyword */
128};
129
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100130/* permit to store configuration section */
131struct cfg_section {
132 struct list list;
133 char *section_name;
134 int (*section_parser)(const char *, int, char **, int);
135};
136
137/* Used to chain configuration sections definitions. This list
138 * stores struct cfg_section
139 */
140struct list sections = LIST_HEAD_INIT(sections);
141
Willy Tarreau13943ab2006-12-31 00:24:10 +0100142/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100144 const char *name;
145 unsigned int val;
146 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100147 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100149};
150
151/* proxy->options */
152static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100153{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
155 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
156 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
157 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
158 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
159 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200161 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200162 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100163 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
165 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
166 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100168#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100170#else
171 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100172#endif
173
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100175};
176
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100177/* proxy->options2 */
178static const struct cfg_opt cfg_opts2[] =
179{
180#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
183 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100184#else
185 { "splice-request", 0, 0, 0, 0 },
186 { "splice-response", 0, 0, 0, 0 },
187 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100188#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100189 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
190 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
191 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
192 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
193 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
194 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
196 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
197 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400198 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100199 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200200 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200201 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100202 { NULL, 0, 0, 0 }
203};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204
Willy Tarreau6daf3432008-01-22 16:44:08 +0100205static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
207int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100208int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100209char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200211/* List head of all known configuration keywords */
212static struct cfg_kw_list cfg_keywords = {
213 .list = LIST_HEAD_INIT(cfg_keywords.list)
214};
215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216/*
217 * converts <str> to a list of listeners which are dynamically allocated.
218 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
219 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
220 * - <port> is a numerical port from 1 to 65535 ;
221 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
222 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
224 * not NULL, it must be a valid pointer to either NULL or a freeable area that
225 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200227int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228{
229 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 int port, end;
232
233 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200234
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100236 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100237 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
239 str = next;
240 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100241 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 *next++ = 0;
243 }
244
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100245 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200246 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200247 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100248 if (!ss2)
249 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100251 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200253 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100257 if (!port || !end) {
258 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
259 goto fail;
260 }
261
Emeric Bruned760922010-10-22 17:59:25 +0200262 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
266
267 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200268 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200269 goto fail;
270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100272 else if (ss2->ss_family == AF_UNSPEC) {
273 socklen_t addr_len;
274
275 /* We want to attach to an already bound fd whose number
276 * is in the addr part of ss2 when cast to sockaddr_in.
277 * Note that by definition there is a single listener.
278 * We still have to determine the address family to
279 * register the correct protocol.
280 */
281 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
282 addr_len = sizeof(*ss2);
283 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
284 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
285 goto fail;
286 }
287
288 port = end = get_host_port(ss2);
289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100291 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200292 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100293
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200295 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100296 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200297 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
298 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
299 l->frontend = curproxy;
300 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301
Willy Tarreau40aa0702013-03-10 23:51:38 +0100302 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200303 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200304 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100305 l->state = LI_INIT;
306
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100307 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100309 tcpv4_add_listener(l);
310 }
Emeric Bruned760922010-10-22 17:59:25 +0200311 else if (ss.ss_family == AF_INET6) {
312 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
313 tcpv6_add_listener(l);
314 }
315 else {
Emeric Bruned760922010-10-22 17:59:25 +0200316 uxst_add_listener(l);
317 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200319 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100320 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321 } /* end for(port) */
322 } /* end while(next) */
323 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200324 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200325 fail:
326 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200327 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328}
329
William Lallemand6e62fb62015-04-28 16:55:23 +0200330/*
331 * Report a fatal Alert when there is too much arguments
332 * The index is the current keyword in args
333 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
334 * Fill err_code with an ERR_ALERT and an ERR_FATAL
335 */
336int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
337{
338 char *kw = NULL;
339 int i;
340
341 if (!*args[index + maxarg + 1])
342 return 0;
343
344 memprintf(&kw, "%s", args[0]);
345 for (i = 1; i <= index; i++) {
346 memprintf(&kw, "%s %s", kw, args[i]);
347 }
348
349 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
350 free(kw);
351 *err_code |= ERR_ALERT | ERR_FATAL;
352 return 1;
353}
354
355/*
356 * same as alertif_too_many_args_idx with a 0 index
357 */
358int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
359{
360 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
361}
362
Willy Tarreau620408f2016-10-21 16:37:51 +0200363/* Report a warning if a rule is placed after a 'tcp-request session' rule.
364 * Return 1 if the warning has been emitted, otherwise 0.
365 */
366int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
367{
368 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
369 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
370 file, line, arg);
371 return 1;
372 }
373 return 0;
374}
375
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200376/* Report a warning if a rule is placed after a 'tcp-request content' rule.
377 * Return 1 if the warning has been emitted, otherwise 0.
378 */
379int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
380{
381 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
382 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
383 file, line, arg);
384 return 1;
385 }
386 return 0;
387}
388
Willy Tarreau61d18892009-03-31 10:49:21 +0200389/* Report a warning if a rule is placed after a 'block' rule.
390 * Return 1 if the warning has been emitted, otherwise 0.
391 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200394 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200395 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
396 file, line, arg);
397 return 1;
398 }
399 return 0;
400}
401
Willy Tarreau5002f572014-04-23 01:32:02 +0200402/* Report a warning if a rule is placed after an 'http_request' rule.
403 * Return 1 if the warning has been emitted, otherwise 0.
404 */
405int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
406{
407 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
408 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
409 file, line, arg);
410 return 1;
411 }
412 return 0;
413}
414
Willy Tarreau61d18892009-03-31 10:49:21 +0200415/* Report a warning if a rule is placed after a reqrewrite rule.
416 * Return 1 if the warning has been emitted, otherwise 0.
417 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100418int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200419{
420 if (proxy->req_exp) {
421 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
422 file, line, arg);
423 return 1;
424 }
425 return 0;
426}
427
428/* Report a warning if a rule is placed after a reqadd rule.
429 * Return 1 if the warning has been emitted, otherwise 0.
430 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100431int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200432{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100433 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200434 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
435 file, line, arg);
436 return 1;
437 }
438 return 0;
439}
440
441/* Report a warning if a rule is placed after a redirect rule.
442 * Return 1 if the warning has been emitted, otherwise 0.
443 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100444int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200445{
446 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
447 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
448 file, line, arg);
449 return 1;
450 }
451 return 0;
452}
453
454/* Report a warning if a rule is placed after a 'use_backend' rule.
455 * Return 1 if the warning has been emitted, otherwise 0.
456 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100457int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200458{
459 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
460 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
461 file, line, arg);
462 return 1;
463 }
464 return 0;
465}
466
Willy Tarreauee445d92014-04-23 01:39:04 +0200467/* Report a warning if a rule is placed after a 'use-server' rule.
468 * Return 1 if the warning has been emitted, otherwise 0.
469 */
470int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
471{
472 if (!LIST_ISEMPTY(&proxy->server_rules)) {
473 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
474 file, line, arg);
475 return 1;
476 }
477 return 0;
478}
479
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200480/* report a warning if a "tcp request connection" rule is dangerously placed */
481int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
482{
Willy Tarreau620408f2016-10-21 16:37:51 +0200483 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
484 warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
485 warnif_rule_after_block(proxy, file, line, arg) ||
486 warnif_rule_after_http_req(proxy, file, line, arg) ||
487 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
488 warnif_rule_after_reqadd(proxy, file, line, arg) ||
489 warnif_rule_after_redirect(proxy, file, line, arg) ||
490 warnif_rule_after_use_backend(proxy, file, line, arg) ||
491 warnif_rule_after_use_server(proxy, file, line, arg);
492}
493
494int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
495{
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200496 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
497 warnif_rule_after_block(proxy, file, line, arg) ||
498 warnif_rule_after_http_req(proxy, file, line, arg) ||
499 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
500 warnif_rule_after_reqadd(proxy, file, line, arg) ||
501 warnif_rule_after_redirect(proxy, file, line, arg) ||
502 warnif_rule_after_use_backend(proxy, file, line, arg) ||
503 warnif_rule_after_use_server(proxy, file, line, arg);
504}
505
506/* report a warning if a "tcp request content" rule is dangerously placed */
507int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
508{
509 return warnif_rule_after_block(proxy, file, line, arg) ||
510 warnif_rule_after_http_req(proxy, file, line, arg) ||
511 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
512 warnif_rule_after_reqadd(proxy, file, line, arg) ||
513 warnif_rule_after_redirect(proxy, file, line, arg) ||
514 warnif_rule_after_use_backend(proxy, file, line, arg) ||
515 warnif_rule_after_use_server(proxy, file, line, arg);
516}
517
Willy Tarreau61d18892009-03-31 10:49:21 +0200518/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100519int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200520{
Willy Tarreau5002f572014-04-23 01:32:02 +0200521 return warnif_rule_after_http_req(proxy, file, line, arg) ||
522 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
523 warnif_rule_after_reqadd(proxy, file, line, arg) ||
524 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200525 warnif_rule_after_use_backend(proxy, file, line, arg) ||
526 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200527}
528
529/* report a warning if an http-request rule is dangerously placed */
530int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
531{
Willy Tarreau61d18892009-03-31 10:49:21 +0200532 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
533 warnif_rule_after_reqadd(proxy, file, line, arg) ||
534 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200535 warnif_rule_after_use_backend(proxy, file, line, arg) ||
536 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200537}
538
539/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100540int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200541{
542 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
543 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200544 warnif_rule_after_use_backend(proxy, file, line, arg) ||
545 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200546}
547
548/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100549int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200550{
551 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200552 warnif_rule_after_use_backend(proxy, file, line, arg) ||
553 warnif_rule_after_use_server(proxy, file, line, arg);
554}
555
556/* report a warning if a redirect rule is dangerously placed */
557int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
558{
559 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
560 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200561}
562
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100563/* Report it if a request ACL condition uses some keywords that are incompatible
564 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
565 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
566 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100569{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100570 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200571 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100573 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100574 return 0;
575
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100576 acl = acl_cond_conflicts(cond, where);
577 if (acl) {
578 if (acl->name && *acl->name)
579 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
580 file, line, acl->name, sample_ckp_names(where));
581 else
582 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200583 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100584 return ERR_WARN;
585 }
586 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100587 return 0;
588
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100589 if (acl->name && *acl->name)
590 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200591 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100592 else
593 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200594 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100595 return ERR_WARN;
596}
597
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200599 * parse a line in a <global> section. Returns the error code, 0 if OK, or
600 * any combination of :
601 * - ERR_ABORT: must abort ASAP
602 * - ERR_FATAL: we can continue parsing but not start the service
603 * - ERR_WARN: a warning has been emitted
604 * - ERR_ALERT: an alert has been emitted
605 * Only the two first ones can stop processing, the two others are just
606 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200608int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609{
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200611 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612
613 if (!strcmp(args[0], "global")) { /* new section */
614 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200615 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200618 else if (!strcmp(args[0], "ca-base")) {
619#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200620 if(alertif_too_many_args(1, file, linenum, args, &err_code))
621 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200622 if (global.ca_base != NULL) {
623 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT;
625 goto out;
626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631 }
632 global.ca_base = strdup(args[1]);
633#else
634 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
637#endif
638 }
639 else if (!strcmp(args[0], "crt-base")) {
640#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200641 if (alertif_too_many_args(1, file, linenum, args, &err_code))
642 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200643 if (global.crt_base != NULL) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.crt_base = strdup(args[1]);
654#else
655 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
656 err_code |= ERR_ALERT | ERR_FATAL;
657 goto out;
658#endif
659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200661 if (alertif_too_many_args(0, file, linenum, args, &err_code))
662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 global.mode |= MODE_DAEMON;
664 }
665 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200666 if (alertif_too_many_args(0, file, linenum, args, &err_code))
667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 global.mode |= MODE_DEBUG;
669 }
670 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200671 if (alertif_too_many_args(0, file, linenum, args, &err_code))
672 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100673 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200675 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200676 if (alertif_too_many_args(0, file, linenum, args, &err_code))
677 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100678 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200681 if (alertif_too_many_args(0, file, linenum, args, &err_code))
682 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100683 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100685 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200686 if (alertif_too_many_args(0, file, linenum, args, &err_code))
687 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100688 global.tune.options &= ~GTUNE_USE_SPLICE;
689 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200690 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200691 if (alertif_too_many_args(0, file, linenum, args, &err_code))
692 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200693 global.tune.options &= ~GTUNE_USE_GAI;
694 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000695 else if (!strcmp(args[0], "noreuseport")) {
696 if (alertif_too_many_args(0, file, linenum, args, &err_code))
697 goto out;
698 global.tune.options &= ~GTUNE_USE_REUSEPORT;
699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200701 if (alertif_too_many_args(0, file, linenum, args, &err_code))
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 global.mode |= MODE_QUIET;
704 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200705 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
707 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200708 if (global.tune.maxpollevents != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200710 err_code |= ERR_ALERT;
711 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200717 }
718 global.tune.maxpollevents = atol(args[1]);
719 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100720 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200721 if (alertif_too_many_args(1, file, linenum, args, &err_code))
722 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100723 if (global.tune.maxaccept != 0) {
724 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT;
726 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100727 }
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100732 }
733 global.tune.maxaccept = atol(args[1]);
734 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200735 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200736 if (alertif_too_many_args(1, file, linenum, args, &err_code))
737 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.chksize = atol(args[1]);
744 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100745 else if (!strcmp(args[0], "tune.recv_enough")) {
746 if (alertif_too_many_args(1, file, linenum, args, &err_code))
747 goto out;
748 if (*(args[1]) == 0) {
749 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
752 }
753 global.tune.recv_enough = atol(args[1]);
754 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200755#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200756 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200757 if (alertif_too_many_args(0, file, linenum, args, &err_code))
758 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200759 global.tune.sslprivatecache = 1;
760 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100761 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
763 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200764 if (*(args[1]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 global.tune.sslcachesize = atol(args[1]);
770 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100771 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
772 unsigned int ssllifetime;
773 const char *res;
774
William Lallemand1a748ae2015-05-19 16:37:23 +0200775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
776 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782
783 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
784 if (res) {
785 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
786 file, linenum, *res, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790
791 global.tune.ssllifetime = ssllifetime;
792 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100793 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200794 if (alertif_too_many_args(1, file, linenum, args, &err_code))
795 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100796 if (*(args[1]) == 0) {
797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801 global.tune.ssl_max_record = atol(args[1]);
802 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200803#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200804 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.ssl_default_dh_param = atol(args[1]);
813 if (global.tune.ssl_default_dh_param < 1024) {
814 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200819#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200820 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.tune.ssl_ctx_cache = atoi(args[1]);
829 if (global.tune.ssl_ctx_cache < 0) {
830 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
831 file, linenum, args[0]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200836#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100837 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200838 if (alertif_too_many_args(1, file, linenum, args, &err_code))
839 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100840 if (*(args[1]) == 0) {
841 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
842 err_code |= ERR_ALERT | ERR_FATAL;
843 goto out;
844 }
845 global.tune.buf_limit = atol(args[1]);
846 if (global.tune.buf_limit) {
847 if (global.tune.buf_limit < 3)
848 global.tune.buf_limit = 3;
849 if (global.tune.buf_limit <= global.tune.reserved_bufs)
850 global.tune.buf_limit = global.tune.reserved_bufs + 1;
851 }
852 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100853 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200854 if (alertif_too_many_args(1, file, linenum, args, &err_code))
855 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100856 if (*(args[1]) == 0) {
857 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
858 err_code |= ERR_ALERT | ERR_FATAL;
859 goto out;
860 }
861 global.tune.reserved_bufs = atol(args[1]);
862 if (global.tune.reserved_bufs < 2)
863 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100864 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
865 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100866 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200867 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200868 if (alertif_too_many_args(1, file, linenum, args, &err_code))
869 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200876 if (global.tune.bufsize <= 0) {
877 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100881 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100882 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200883 }
884 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200885 if (alertif_too_many_args(1, file, linenum, args, &err_code))
886 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200893 if (global.tune.maxrewrite < 0) {
894 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200898 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100899 else if (!strcmp(args[0], "tune.idletimer")) {
900 unsigned int idle;
901 const char *res;
902
William Lallemand1a748ae2015-05-19 16:37:23 +0200903 if (alertif_too_many_args(1, file, linenum, args, &err_code))
904 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100905 if (*(args[1]) == 0) {
906 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910
911 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
912 if (res) {
913 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
914 file, linenum, *res, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918
919 if (idle > 65535) {
920 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
923 }
924 global.tune.idle_timer = idle;
925 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100926 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200927 if (alertif_too_many_args(1, file, linenum, args, &err_code))
928 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100929 if (global.tune.client_rcvbuf != 0) {
930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT;
932 goto out;
933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.tune.client_rcvbuf = atol(args[1]);
940 }
941 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200942 if (alertif_too_many_args(1, file, linenum, args, &err_code))
943 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100944 if (global.tune.server_rcvbuf != 0) {
945 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
946 err_code |= ERR_ALERT;
947 goto out;
948 }
949 if (*(args[1]) == 0) {
950 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 global.tune.server_rcvbuf = atol(args[1]);
955 }
956 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200957 if (alertif_too_many_args(1, file, linenum, args, &err_code))
958 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100959 if (global.tune.client_sndbuf != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
961 err_code |= ERR_ALERT;
962 goto out;
963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.tune.client_sndbuf = atol(args[1]);
970 }
971 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200972 if (alertif_too_many_args(1, file, linenum, args, &err_code))
973 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100974 if (global.tune.server_sndbuf != 0) {
975 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
976 err_code |= ERR_ALERT;
977 goto out;
978 }
979 if (*(args[1]) == 0) {
980 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
983 }
984 global.tune.server_sndbuf = atol(args[1]);
985 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200986 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200987 if (alertif_too_many_args(1, file, linenum, args, &err_code))
988 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993 }
994 global.tune.pipesize = atol(args[1]);
995 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100996 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200997 if (alertif_too_many_args(1, file, linenum, args, &err_code))
998 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 global.tune.cookie_len = atol(args[1]) + 1;
1005 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001006 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001007 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1008 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +02001009 if (*(args[1]) == 0) {
1010 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.tune.max_http_hdr = atol(args[1]);
1015 }
William Lallemanda509e4c2012-11-07 16:54:34 +01001016 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
1017#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001018 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1019 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001020 if (*args[1]) {
1021 global.tune.zlibmemlevel = atoi(args[1]);
1022 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
1023 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1024 file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 } else {
1029 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1030 file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034#else
1035 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038#endif
1039 }
1040 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1041#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001042 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1043 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001044 if (*args[1]) {
1045 global.tune.zlibwindowsize = atoi(args[1]);
1046 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1047 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1048 file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 } else {
1053 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1054 file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058#else
1059 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062#endif
1063 }
William Lallemandf3747832012-11-09 12:33:10 +01001064 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001065 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1066 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001067 if (*args[1]) {
1068 global.tune.comp_maxlevel = atoi(args[1]);
1069 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1070 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1071 file, linenum, args[0]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 } else {
1076 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1077 file, linenum, args[0]);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001082 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1083 if (*args[1]) {
1084 global.tune.pattern_cache = atoi(args[1]);
1085 if (global.tune.pattern_cache < 0) {
1086 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1087 file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 } else {
1092 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1093 file, linenum, args[0]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001099 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001102 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001103 err_code |= ERR_ALERT;
1104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 }
1106 if (*(args[1]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001111 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1112 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
1113 err_code |= ERR_WARN;
1114 goto out;
1115 }
1116
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 }
1118 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001119 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001122 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 }
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001131 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1132 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
1133 err_code |= ERR_WARN;
1134 goto out;
1135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
Simon Horman98637e52014-06-20 12:30:16 +09001137 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001138 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1139 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001140 global.external_check = 1;
1141 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001142 /* user/group name handling */
1143 else if (!strcmp(args[0], "user")) {
1144 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001145 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1146 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001147 if (global.uid != 0) {
1148 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT;
1150 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001151 }
1152 errno = 0;
1153 ha_user = getpwnam(args[1]);
1154 if (ha_user != NULL) {
1155 global.uid = (int)ha_user->pw_uid;
1156 }
1157 else {
1158 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001160 }
1161 }
1162 else if (!strcmp(args[0], "group")) {
1163 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001164 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1165 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001166 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001167 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001168 err_code |= ERR_ALERT;
1169 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001170 }
1171 errno = 0;
1172 ha_group = getgrnam(args[1]);
1173 if (ha_group != NULL) {
1174 global.gid = (int)ha_group->gr_gid;
1175 }
1176 else {
1177 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001178 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001179 }
1180 }
1181 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001183 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185 if (*(args[1]) == 0) {
1186 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 }
1190 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001191 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1192 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1193 file, linenum, args[0], LONGBITS, global.nbproc);
1194 err_code |= ERR_ALERT | ERR_FATAL;
1195 goto out;
1196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 }
1198 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001199 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 if (global.maxconn != 0) {
1202 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001203 err_code |= ERR_ALERT;
1204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
1206 if (*(args[1]) == 0) {
1207 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 }
1211 global.maxconn = atol(args[1]);
1212#ifdef SYSTEM_MAXCONN
1213 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1214 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1215 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001216 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218#endif /* SYSTEM_MAXCONN */
1219 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001220 else if (!strcmp(args[0], "maxsslconn")) {
1221#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001222 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1223 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 global.maxsslconn = atol(args[1]);
1230#else
Emeric Brun0914df82012-10-02 18:45:42 +02001231 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001234#endif
1235 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001236 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1237#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001238 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1239 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001240 if (*(args[1]) == 0) {
1241 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245 free(global.listen_default_ciphers);
1246 global.listen_default_ciphers = strdup(args[1]);
1247#else
1248 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251#endif
1252 }
1253 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1254#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001255 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1256 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001257 if (*(args[1]) == 0) {
1258 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262 free(global.connect_default_ciphers);
1263 global.connect_default_ciphers = strdup(args[1]);
1264#else
1265 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268#endif
1269 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001270#ifdef USE_OPENSSL
1271#ifndef OPENSSL_NO_DH
1272 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1273 if (*(args[1]) == 0) {
1274 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1279 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282 }
1283 }
1284#endif
1285#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001286 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001287 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1288 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001289 if (*(args[1]) == 0) {
1290 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
1293 }
1294 if (strcmp(args[1],"none") == 0)
1295 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1296 else if (strcmp(args[1],"required") == 0)
1297 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1298 else {
1299 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001304 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001305 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1306 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001307 if (global.cps_lim != 0) {
1308 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1309 err_code |= ERR_ALERT;
1310 goto out;
1311 }
1312 if (*(args[1]) == 0) {
1313 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1314 err_code |= ERR_ALERT | ERR_FATAL;
1315 goto out;
1316 }
1317 global.cps_lim = atol(args[1]);
1318 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001319 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001320 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1321 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001322 if (global.sps_lim != 0) {
1323 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1324 err_code |= ERR_ALERT;
1325 goto out;
1326 }
1327 if (*(args[1]) == 0) {
1328 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332 global.sps_lim = atol(args[1]);
1333 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001334 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001335 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1336 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001337 if (global.ssl_lim != 0) {
1338 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1339 err_code |= ERR_ALERT;
1340 goto out;
1341 }
1342 if (*(args[1]) == 0) {
1343 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
1346 }
1347 global.ssl_lim = atol(args[1]);
1348 }
William Lallemandd85f9172012-11-09 17:05:39 +01001349 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001350 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1351 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001352 if (*(args[1]) == 0) {
1353 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357 global.comp_rate_lim = atoi(args[1]) * 1024;
1358 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001359 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001360 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1361 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001362 if (global.maxpipes != 0) {
1363 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001364 err_code |= ERR_ALERT;
1365 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001366 }
1367 if (*(args[1]) == 0) {
1368 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001369 err_code |= ERR_ALERT | ERR_FATAL;
1370 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001371 }
1372 global.maxpipes = atol(args[1]);
1373 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001374 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001375 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1376 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001377 if (*(args[1]) == 0) {
1378 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto out;
1381 }
William Lallemande3a7d992012-11-20 11:25:20 +01001382 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001383 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001384 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001385 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1386 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001387 if (*(args[1]) == 0) {
1388 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1389 err_code |= ERR_ALERT | ERR_FATAL;
1390 goto out;
1391 }
1392 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001393 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001394 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
1397 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001398 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001399
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001401 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 if (global.rlimit_nofile != 0) {
1404 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001405 err_code |= ERR_ALERT;
1406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 }
1408 if (*(args[1]) == 0) {
1409 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 }
1413 global.rlimit_nofile = atol(args[1]);
1414 }
1415 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001416 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 if (global.chroot != NULL) {
1419 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001420 err_code |= ERR_ALERT;
1421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 }
1423 if (*(args[1]) == 0) {
1424 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001425 err_code |= ERR_ALERT | ERR_FATAL;
1426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 }
1428 global.chroot = strdup(args[1]);
1429 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001430 else if (!strcmp(args[0], "description")) {
1431 int i, len=0;
1432 char *d;
1433
1434 if (!*args[1]) {
1435 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1436 file, linenum, args[0]);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 goto out;
1439 }
1440
Willy Tarreau348acfe2014-04-14 15:00:39 +02001441 for (i = 1; *args[i]; i++)
1442 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001443
1444 if (global.desc)
1445 free(global.desc);
1446
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001447 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001448
Willy Tarreau348acfe2014-04-14 15:00:39 +02001449 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1450 for (i = 2; *args[i]; i++)
1451 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001452 }
1453 else if (!strcmp(args[0], "node")) {
1454 int i;
1455 char c;
1456
William Lallemand1a748ae2015-05-19 16:37:23 +02001457 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1458 goto out;
1459
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001460 for (i=0; args[1][i]; i++) {
1461 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001462 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1463 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001464 break;
1465 }
1466
1467 if (!i || args[1][i]) {
1468 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1469 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1470 file, linenum, args[0]);
1471 err_code |= ERR_ALERT | ERR_FATAL;
1472 goto out;
1473 }
1474
1475 if (global.node)
1476 free(global.node);
1477
1478 global.node = strdup(args[1]);
1479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001481 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 if (global.pidfile != NULL) {
1484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001485 err_code |= ERR_ALERT;
1486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 }
1488 if (*(args[1]) == 0) {
1489 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 }
1493 global.pidfile = strdup(args[1]);
1494 }
Emeric Bruned760922010-10-22 17:59:25 +02001495 else if (!strcmp(args[0], "unix-bind")) {
1496 int cur_arg = 1;
1497 while (*(args[cur_arg])) {
1498 if (!strcmp(args[cur_arg], "prefix")) {
1499 if (global.unix_bind.prefix != NULL) {
1500 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1501 err_code |= ERR_ALERT;
1502 cur_arg += 2;
1503 continue;
1504 }
1505
1506 if (*(args[cur_arg+1]) == 0) {
1507 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto out;
1510 }
1511 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1512 cur_arg += 2;
1513 continue;
1514 }
1515
1516 if (!strcmp(args[cur_arg], "mode")) {
1517
1518 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1519 cur_arg += 2;
1520 continue;
1521 }
1522
1523 if (!strcmp(args[cur_arg], "uid")) {
1524
1525 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1526 cur_arg += 2;
1527 continue;
1528 }
1529
1530 if (!strcmp(args[cur_arg], "gid")) {
1531
1532 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1533 cur_arg += 2;
1534 continue;
1535 }
1536
1537 if (!strcmp(args[cur_arg], "user")) {
1538 struct passwd *user;
1539
1540 user = getpwnam(args[cur_arg + 1]);
1541 if (!user) {
1542 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1543 file, linenum, args[0], args[cur_arg + 1 ]);
1544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
1547
1548 global.unix_bind.ux.uid = user->pw_uid;
1549 cur_arg += 2;
1550 continue;
1551 }
1552
1553 if (!strcmp(args[cur_arg], "group")) {
1554 struct group *group;
1555
1556 group = getgrnam(args[cur_arg + 1]);
1557 if (!group) {
1558 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1559 file, linenum, args[0], args[cur_arg + 1 ]);
1560 err_code |= ERR_ALERT | ERR_FATAL;
1561 goto out;
1562 }
1563
1564 global.unix_bind.ux.gid = group->gr_gid;
1565 cur_arg += 2;
1566 continue;
1567 }
1568
Willy Tarreaub48f9582011-09-05 01:17:06 +02001569 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001570 file, linenum, args[0]);
1571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
1573 }
1574 }
William Lallemand0f99e342011-10-12 17:50:54 +02001575 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1576 /* delete previous herited or defined syslog servers */
1577 struct logsrv *back;
1578 struct logsrv *tmp;
1579
1580 if (*(args[1]) != 0) {
1581 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1582 err_code |= ERR_ALERT | ERR_FATAL;
1583 goto out;
1584 }
1585
1586 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1587 LIST_DEL(&tmp->list);
1588 free(tmp);
1589 }
1590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001592 struct sockaddr_storage *sk;
1593 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001594 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001595 int arg = 0;
1596 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001597
William Lallemand1a748ae2015-05-19 16:37:23 +02001598 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1599 goto out;
1600
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 if (*(args[1]) == 0 || *(args[2]) == 0) {
1602 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
1604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
William Lallemand0f99e342011-10-12 17:50:54 +02001606
Vincent Bernat02779b62016-04-03 13:48:43 +02001607 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001608
Willy Tarreau18324f52014-06-27 18:10:07 +02001609 /* just after the address, a length may be specified */
1610 if (strcmp(args[arg+2], "len") == 0) {
1611 len = atoi(args[arg+3]);
1612 if (len < 80 || len > 65535) {
1613 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1614 file, linenum, args[arg+3]);
1615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
1617 }
1618 logsrv->maxlen = len;
1619
1620 /* skip these two args */
1621 arg += 2;
1622 }
1623 else
1624 logsrv->maxlen = MAX_SYSLOG_LEN;
1625
1626 if (logsrv->maxlen > global.max_syslog_len) {
1627 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001628 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1629 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1630 logline = my_realloc2(logline, global.max_syslog_len + 1);
1631 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001632 }
1633
Dragan Dosen1322d092015-09-22 16:05:32 +02001634 /* after the length, a format may be specified */
1635 if (strcmp(args[arg+2], "format") == 0) {
1636 logsrv->format = get_log_format(args[arg+3]);
1637 if (logsrv->format < 0) {
1638 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1639 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001640 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001641 goto out;
1642 }
1643
1644 /* skip these two args */
1645 arg += 2;
1646 }
1647
David Carlier97880bb2016-04-08 10:35:26 +01001648 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1649 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001650 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001651 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001652
Willy Tarreau18324f52014-06-27 18:10:07 +02001653 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001654 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001655 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001657 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 }
1659
William Lallemand0f99e342011-10-12 17:50:54 +02001660 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001661 if (*(args[arg+3])) {
1662 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001663 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001664 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001666 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 }
1668 }
1669
William Lallemand0f99e342011-10-12 17:50:54 +02001670 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001671 if (*(args[arg+4])) {
1672 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001673 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001674 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001676 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001677 }
1678 }
1679
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001680 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001681 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001682 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001683 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001684 free(logsrv);
1685 goto out;
1686 }
1687 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001688
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001689 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001690 if (port1 != port2) {
1691 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1692 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001693 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001694 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001695 goto out;
1696 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001697
William Lallemand0f99e342011-10-12 17:50:54 +02001698 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001699 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001700 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702
William Lallemand0f99e342011-10-12 17:50:54 +02001703 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001704 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001705 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1706 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001707
1708 if (global.log_send_hostname != NULL) {
1709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1710 err_code |= ERR_ALERT;
1711 goto out;
1712 }
1713
1714 if (*(args[1]))
1715 name = args[1];
1716 else
1717 name = hostname;
1718
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001719 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001720 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001721 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001722 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1723 if (global.server_state_base != NULL) {
1724 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1725 err_code |= ERR_ALERT;
1726 goto out;
1727 }
1728
1729 if (!*(args[1])) {
1730 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1731 err_code |= ERR_FATAL;
1732 goto out;
1733 }
1734
1735 global.server_state_base = strdup(args[1]);
1736 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001737 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1738 if (global.server_state_file != NULL) {
1739 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1740 err_code |= ERR_ALERT;
1741 goto out;
1742 }
1743
1744 if (!*(args[1])) {
1745 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1746 err_code |= ERR_FATAL;
1747 goto out;
1748 }
1749
1750 global.server_state_file = strdup(args[1]);
1751 }
Kevinm48936af2010-12-22 16:08:21 +00001752 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001753 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1754 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001755 if (*(args[1]) == 0) {
1756 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001760 chunk_destroy(&global.log_tag);
1761 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001762 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001763 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001764 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1765 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001766 if (global.spread_checks != 0) {
1767 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001768 err_code |= ERR_ALERT;
1769 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001770 }
1771 if (*(args[1]) == 0) {
1772 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001775 }
1776 global.spread_checks = atol(args[1]);
1777 if (global.spread_checks < 0 || global.spread_checks > 50) {
1778 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001779 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001782 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1783 const char *err;
1784 unsigned int val;
1785
William Lallemand1a748ae2015-05-19 16:37:23 +02001786 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1787 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001788 if (*(args[1]) == 0) {
1789 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
1792 }
1793
1794 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1795 if (err) {
1796 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 }
1799 global.max_spread_checks = val;
1800 if (global.max_spread_checks < 0) {
1801 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 }
1804 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001805 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1806#ifdef USE_CPU_AFFINITY
1807 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001808 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001809 unsigned long cpus = 0;
1810
1811 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001812 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001813 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001814 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001815 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001816 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001817 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001818 proc = atol(args[1]);
1819 if (proc >= 1 && proc <= LONGBITS)
1820 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001821 }
1822
1823 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001824 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1825 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
1828 }
1829
1830 cur_arg = 2;
1831 while (*args[cur_arg]) {
1832 unsigned int low, high;
1833
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001834 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001835 char *dash = strchr(args[cur_arg], '-');
1836
1837 low = high = str2uic(args[cur_arg]);
1838 if (dash)
1839 high = str2uic(dash + 1);
1840
1841 if (high < low) {
1842 unsigned int swap = low;
1843 low = high;
1844 high = swap;
1845 }
1846
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001847 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001848 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001849 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001850 err_code |= ERR_ALERT | ERR_FATAL;
1851 goto out;
1852 }
1853
1854 while (low <= high)
1855 cpus |= 1UL << low++;
1856 }
1857 else {
1858 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1859 file, linenum, args[0], args[cur_arg]);
1860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
1862 }
1863 cur_arg++;
1864 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001865 for (i = 0; i < LONGBITS; i++)
1866 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001867 global.cpu_map[i] = cpus;
1868#else
1869 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872#endif
1873 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001874 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1875 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1876 goto out;
1877
1878 if (*(args[2]) == 0) {
1879 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
1882 }
1883
1884 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1885 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1886 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
1889 }
1890 }
1891 else if (!strcmp(args[0], "unsetenv")) {
1892 int arg;
1893
1894 if (*(args[1]) == 0) {
1895 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
1898 }
1899
1900 for (arg = 1; *args[arg]; arg++) {
1901 if (unsetenv(args[arg]) != 0) {
1902 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1903 err_code |= ERR_ALERT | ERR_FATAL;
1904 goto out;
1905 }
1906 }
1907 }
1908 else if (!strcmp(args[0], "resetenv")) {
1909 extern char **environ;
1910 char **env = environ;
1911
1912 /* args contain variable names to keep, one per argument */
1913 while (*env) {
1914 int arg;
1915
1916 /* look for current variable in among all those we want to keep */
1917 for (arg = 1; *args[arg]; arg++) {
1918 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1919 (*env)[strlen(args[arg])] == '=')
1920 break;
1921 }
1922
1923 /* delete this variable */
1924 if (!*args[arg]) {
1925 char *delim = strchr(*env, '=');
1926
1927 if (!delim || delim - *env >= trash.size) {
1928 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
1931 }
1932
1933 memcpy(trash.str, *env, delim - *env);
1934 trash.str[delim - *env] = 0;
1935
1936 if (unsetenv(trash.str) != 0) {
1937 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
1940 }
1941 }
1942 else
1943 env++;
1944 }
1945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001947 struct cfg_kw_list *kwl;
1948 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001949 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001950
1951 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1952 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1953 if (kwl->kw[index].section != CFG_GLOBAL)
1954 continue;
1955 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001956 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001957 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001958 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001959 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001960 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001961 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001962 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001963 err_code |= ERR_WARN;
1964 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001965 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001966 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001967 }
1968 }
1969 }
1970
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001972 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001974
Willy Tarreau058e9072009-07-20 09:30:05 +02001975 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001976 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001977 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978}
1979
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001980void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001982 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 defproxy.mode = PR_MODE_TCP;
1984 defproxy.state = PR_STNEW;
1985 defproxy.maxconn = cfg_maxpconn;
1986 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001987 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001988 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001989
Simon Horman66183002013-02-23 10:16:43 +09001990 defproxy.defsrv.check.inter = DEF_CHKINTR;
1991 defproxy.defsrv.check.fastinter = 0;
1992 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001993 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1994 defproxy.defsrv.agent.fastinter = 0;
1995 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001996 defproxy.defsrv.check.rise = DEF_RISETIME;
1997 defproxy.defsrv.check.fall = DEF_FALLTIME;
1998 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1999 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02002000 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09002001 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002002 defproxy.defsrv.maxqueue = 0;
2003 defproxy.defsrv.minconn = 0;
2004 defproxy.defsrv.maxconn = 0;
2005 defproxy.defsrv.slowstart = 0;
2006 defproxy.defsrv.onerror = DEF_HANA_ONERR;
2007 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
2008 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09002009
2010 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002011 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012}
2013
Willy Tarreauade5ec42010-01-28 19:33:49 +01002014
Willy Tarreau63af98d2014-05-18 08:11:41 +02002015/* This function createss a new req* or rsp* rule to the proxy. It compiles the
2016 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
2017 * ERR_FATAL in case of error.
2018 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01002019static int create_cond_regex_rule(const char *file, int line,
2020 struct proxy *px, int dir, int action, int flags,
2021 const char *cmd, const char *reg, const char *repl,
2022 const char **cond_start)
2023{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002024 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002025 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002026 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002027 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002028 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002029 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002030 int cs;
2031 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002032
2033 if (px == &defproxy) {
2034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002035 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002036 goto err;
2037 }
2038
2039 if (*reg == 0) {
2040 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002041 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002042 goto err;
2043 }
2044
Christopher Faulet898566e2016-10-26 11:06:28 +02002045 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002046 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002047
Willy Tarreau5321c422010-01-28 20:35:13 +01002048 if (cond_start &&
2049 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002050 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2051 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2052 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002053 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002054 goto err;
2055 }
2056 }
2057 else if (cond_start && **cond_start) {
2058 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2059 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002060 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002061 goto err;
2062 }
2063
Willy Tarreau63af98d2014-05-18 08:11:41 +02002064 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002065 (dir == SMP_OPT_DIR_REQ) ?
2066 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2067 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2068 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002069
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002070 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002071 if (!preg) {
2072 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002073 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002074 goto err;
2075 }
2076
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002077 cs = !(flags & REG_ICASE);
2078 cap = !(flags & REG_NOSUB);
2079 error = NULL;
2080 if (!regex_comp(reg, preg, cs, cap, &error)) {
2081 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2082 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002083 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002084 goto err;
2085 }
2086
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002087 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002088 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002089 if (repl && err) {
2090 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2091 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002092 ret_code |= ERR_ALERT | ERR_FATAL;
2093 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002094 }
2095
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002096 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002097 ret_code |= ERR_WARN;
2098
2099 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002100
Willy Tarreau63af98d2014-05-18 08:11:41 +02002101 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002102 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002103 err:
2104 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002105 free(errmsg);
2106 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002107}
2108
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109/*
William Lallemand51097192015-04-14 16:35:22 +02002110 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002111 * Returns the error code, 0 if OK, or any combination of :
2112 * - ERR_ABORT: must abort ASAP
2113 * - ERR_FATAL: we can continue parsing but not start the service
2114 * - ERR_WARN: a warning has been emitted
2115 * - ERR_ALERT: an alert has been emitted
2116 * Only the two first ones can stop processing, the two others are just
2117 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002119int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2120{
2121 static struct peers *curpeers = NULL;
2122 struct peer *newpeer = NULL;
2123 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002124 struct bind_conf *bind_conf;
2125 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002126 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002127 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002128
2129 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002130 if (!*args[1]) {
2131 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002132 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002133 goto out;
2134 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002135
William Lallemand6e62fb62015-04-28 16:55:23 +02002136 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2137 goto out;
2138
Emeric Brun32da3c42010-09-23 18:39:19 +02002139 err = invalid_char(args[1]);
2140 if (err) {
2141 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2142 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002143 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002144 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002145 }
2146
2147 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2148 /*
2149 * If there are two proxies with the same name only following
2150 * combinations are allowed:
2151 */
2152 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002153 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02002154 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002156 }
2157 }
2158
Vincent Bernat02779b62016-04-03 13:48:43 +02002159 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002160 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2161 err_code |= ERR_ALERT | ERR_ABORT;
2162 goto out;
2163 }
2164
2165 curpeers->next = peers;
2166 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002167 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002168 curpeers->conf.line = linenum;
2169 curpeers->last_change = now.tv_sec;
2170 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002171 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002172 }
2173 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002174 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002175 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002176 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002177
2178 if (!*args[2]) {
2179 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2180 file, linenum, args[0]);
2181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
2183 }
2184
2185 err = invalid_char(args[1]);
2186 if (err) {
2187 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2188 file, linenum, *err, args[1]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
Vincent Bernat02779b62016-04-03 13:48:43 +02002193 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2195 err_code |= ERR_ALERT | ERR_ABORT;
2196 goto out;
2197 }
2198
2199 /* the peers are linked backwards first */
2200 curpeers->count++;
2201 newpeer->next = curpeers->remote;
2202 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002203 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002204 newpeer->conf.line = linenum;
2205
2206 newpeer->last_change = now.tv_sec;
2207 newpeer->id = strdup(args[1]);
2208
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002209 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002210 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002211 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002214 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002215
2216 proto = protocol_by_family(sk->ss_family);
2217 if (!proto || !proto->connect) {
2218 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2219 file, linenum, args[0], args[1]);
2220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
2222 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002223
2224 if (port1 != port2) {
2225 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2226 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
2229 }
2230
Willy Tarreau2aa38802013-02-20 19:20:59 +01002231 if (!port1) {
2232 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2233 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002237
Emeric Brun32da3c42010-09-23 18:39:19 +02002238 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002239 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002240 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002241 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002242
Emeric Brun32da3c42010-09-23 18:39:19 +02002243 if (strcmp(newpeer->id, localpeer) == 0) {
2244 /* Current is local peer, it define a frontend */
2245 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002246 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002247
2248 if (!curpeers->peers_fe) {
2249 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2251 err_code |= ERR_ALERT | ERR_ABORT;
2252 goto out;
2253 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002254
Willy Tarreau237250c2011-07-29 01:49:03 +02002255 init_new_proxy(curpeers->peers_fe);
2256 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002257 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002258 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2259 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002260 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002261
2262 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2263
Willy Tarreau902636f2013-03-10 19:44:48 +01002264 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2265 if (errmsg && *errmsg) {
2266 indent_msg(&errmsg, 2);
2267 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002268 }
2269 else
2270 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2271 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002272 err_code |= ERR_FATAL;
2273 goto out;
2274 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002275
2276 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002277 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002278 l->maxconn = curpeers->peers_fe->maxconn;
2279 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002280 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002281 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002282 l->analysers |= curpeers->peers_fe->fe_req_ana;
2283 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002284 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2285 global.maxsock += l->maxconn;
2286 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002287 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002288 else {
2289 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2290 file, linenum, args[0], args[1],
2291 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2292 err_code |= ERR_FATAL;
2293 goto out;
2294 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002295 }
2296 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002297 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2298 curpeers->state = PR_STSTOPPED;
2299 }
2300 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2301 curpeers->state = PR_STNEW;
2302 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002303 else if (*args[0] != 0) {
2304 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308
2309out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002310 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002311 return err_code;
2312}
2313
Baptiste Assmann325137d2015-04-13 23:40:55 +02002314/*
2315 * Parse a <resolvers> section.
2316 * Returns the error code, 0 if OK, or any combination of :
2317 * - ERR_ABORT: must abort ASAP
2318 * - ERR_FATAL: we can continue parsing but not start the service
2319 * - ERR_WARN: a warning has been emitted
2320 * - ERR_ALERT: an alert has been emitted
2321 * Only the two first ones can stop processing, the two others are just
2322 * indicators.
2323 */
2324int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2325{
2326 static struct dns_resolvers *curr_resolvers = NULL;
2327 struct dns_nameserver *newnameserver = NULL;
2328 const char *err;
2329 int err_code = 0;
2330 char *errmsg = NULL;
2331
2332 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2333 if (!*args[1]) {
2334 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2335 err_code |= ERR_ALERT | ERR_ABORT;
2336 goto out;
2337 }
2338
2339 err = invalid_char(args[1]);
2340 if (err) {
2341 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2342 file, linenum, *err, args[0], args[1]);
2343 err_code |= ERR_ALERT | ERR_ABORT;
2344 goto out;
2345 }
2346
2347 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2348 /* Error if two resolvers owns the same name */
2349 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2350 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2351 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2352 err_code |= ERR_ALERT | ERR_ABORT;
2353 }
2354 }
2355
Vincent Bernat02779b62016-04-03 13:48:43 +02002356 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2358 err_code |= ERR_ALERT | ERR_ABORT;
2359 goto out;
2360 }
2361
2362 /* default values */
2363 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2364 curr_resolvers->conf.file = strdup(file);
2365 curr_resolvers->conf.line = linenum;
2366 curr_resolvers->id = strdup(args[1]);
2367 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002368 /* default hold period for nx, other, refuse and timeout is 30s */
2369 curr_resolvers->hold.nx = 30000;
2370 curr_resolvers->hold.other = 30000;
2371 curr_resolvers->hold.refused = 30000;
2372 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002373 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002374 curr_resolvers->hold.valid = 10000;
2375 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002376 curr_resolvers->resolve_retries = 3;
2377 LIST_INIT(&curr_resolvers->nameserver_list);
2378 LIST_INIT(&curr_resolvers->curr_resolution);
2379 }
2380 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2381 struct sockaddr_storage *sk;
2382 int port1, port2;
2383 struct protocol *proto;
2384
2385 if (!*args[2]) {
2386 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2387 file, linenum, args[0]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
2392 err = invalid_char(args[1]);
2393 if (err) {
2394 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2395 file, linenum, *err, args[1]);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
2398 }
2399
Baptiste Assmanna315c552015-11-02 22:55:49 +01002400 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2401 /* Error if two resolvers owns the same name */
2402 if (strcmp(newnameserver->id, args[1]) == 0) {
2403 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2404 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2405 err_code |= ERR_ALERT | ERR_FATAL;
2406 }
2407 }
2408
Vincent Bernat02779b62016-04-03 13:48:43 +02002409 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002410 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2411 err_code |= ERR_ALERT | ERR_ABORT;
2412 goto out;
2413 }
2414
2415 /* the nameservers are linked backward first */
2416 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2417 curr_resolvers->count_nameservers++;
2418 newnameserver->resolvers = curr_resolvers;
2419 newnameserver->conf.file = strdup(file);
2420 newnameserver->conf.line = linenum;
2421 newnameserver->id = strdup(args[1]);
2422
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002423 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002424 if (!sk) {
2425 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 proto = protocol_by_family(sk->ss_family);
2431 if (!proto || !proto->connect) {
2432 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2433 file, linenum, args[0], args[1]);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437
2438 if (port1 != port2) {
2439 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2440 file, linenum, args[0], args[1], args[2]);
2441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
2443 }
2444
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002445 if (!port1 && !port2) {
2446 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2447 file, linenum, args[0], args[1]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451
Baptiste Assmann325137d2015-04-13 23:40:55 +02002452 newnameserver->addr = *sk;
2453 }
2454 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2455 const char *res;
2456 unsigned int time;
2457
2458 if (!*args[2]) {
2459 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2460 file, linenum, args[0]);
2461 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2466 if (res) {
2467 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2468 file, linenum, *res, args[0]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002472 if (strcmp(args[1], "nx") == 0)
2473 curr_resolvers->hold.nx = time;
2474 else if (strcmp(args[1], "other") == 0)
2475 curr_resolvers->hold.other = time;
2476 else if (strcmp(args[1], "refused") == 0)
2477 curr_resolvers->hold.refused = time;
2478 else if (strcmp(args[1], "timeout") == 0)
2479 curr_resolvers->hold.timeout = time;
2480 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002481 curr_resolvers->hold.valid = time;
2482 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002483 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2484 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488
2489 }
2490 else if (strcmp(args[0], "resolve_retries") == 0) {
2491 if (!*args[1]) {
2492 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2493 file, linenum, args[0]);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497 curr_resolvers->resolve_retries = atoi(args[1]);
2498 }
2499 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002500 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002501 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2502 file, linenum, args[0]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002506 else if (strcmp(args[1], "retry") == 0) {
2507 const char *res;
2508 unsigned int timeout_retry;
2509
2510 if (!*args[2]) {
2511 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2512 file, linenum, args[0], args[1]);
2513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
2515 }
2516 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2517 if (res) {
2518 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2519 file, linenum, *res, args[0], args[1]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523 curr_resolvers->timeout.retry = timeout_retry;
2524 }
2525 else {
2526 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2527 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
2530 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002531 } /* neither "nameserver" nor "resolvers" */
2532 else if (*args[0] != 0) {
2533 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
2536 }
2537
2538 out:
2539 free(errmsg);
2540 return err_code;
2541}
Simon Horman0d16a402015-01-30 11:22:58 +09002542
2543/*
William Lallemand51097192015-04-14 16:35:22 +02002544 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002545 * Returns the error code, 0 if OK, or any combination of :
2546 * - ERR_ABORT: must abort ASAP
2547 * - ERR_FATAL: we can continue parsing but not start the service
2548 * - ERR_WARN: a warning has been emitted
2549 * - ERR_ALERT: an alert has been emitted
2550 * Only the two first ones can stop processing, the two others are just
2551 * indicators.
2552 */
2553int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2554{
2555 static struct mailers *curmailers = NULL;
2556 struct mailer *newmailer = NULL;
2557 const char *err;
2558 int err_code = 0;
2559 char *errmsg = NULL;
2560
2561 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2562 if (!*args[1]) {
2563 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2564 err_code |= ERR_ALERT | ERR_ABORT;
2565 goto out;
2566 }
2567
2568 err = invalid_char(args[1]);
2569 if (err) {
2570 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2571 file, linenum, *err, args[0], args[1]);
2572 err_code |= ERR_ALERT | ERR_ABORT;
2573 goto out;
2574 }
2575
2576 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2577 /*
2578 * If there are two proxies with the same name only following
2579 * combinations are allowed:
2580 */
2581 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002582 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002583 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002585 }
2586 }
2587
Vincent Bernat02779b62016-04-03 13:48:43 +02002588 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2590 err_code |= ERR_ALERT | ERR_ABORT;
2591 goto out;
2592 }
2593
2594 curmailers->next = mailers;
2595 mailers = curmailers;
2596 curmailers->conf.file = strdup(file);
2597 curmailers->conf.line = linenum;
2598 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002599 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2600 * But need enough time so that timeouts don't occur
2601 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002602 }
2603 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2604 struct sockaddr_storage *sk;
2605 int port1, port2;
2606 struct protocol *proto;
2607
2608 if (!*args[2]) {
2609 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2610 file, linenum, args[0]);
2611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
2613 }
2614
2615 err = invalid_char(args[1]);
2616 if (err) {
2617 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2618 file, linenum, *err, args[1]);
2619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
2621 }
2622
Vincent Bernat02779b62016-04-03 13:48:43 +02002623 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002624 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2625 err_code |= ERR_ALERT | ERR_ABORT;
2626 goto out;
2627 }
2628
2629 /* the mailers are linked backwards first */
2630 curmailers->count++;
2631 newmailer->next = curmailers->mailer_list;
2632 curmailers->mailer_list = newmailer;
2633 newmailer->mailers = curmailers;
2634 newmailer->conf.file = strdup(file);
2635 newmailer->conf.line = linenum;
2636
2637 newmailer->id = strdup(args[1]);
2638
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002639 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002640 if (!sk) {
2641 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
2646 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002647 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2648 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002649 file, linenum, args[0], args[1]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653
2654 if (port1 != port2) {
2655 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2656 file, linenum, args[0], args[1], args[2]);
2657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
2659 }
2660
2661 if (!port1) {
2662 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2663 file, linenum, args[0], args[1], args[2]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
2668 newmailer->addr = *sk;
2669 newmailer->proto = proto;
2670 newmailer->xprt = &raw_sock;
2671 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002672 }
2673 else if (strcmp(args[0], "timeout") == 0) {
2674 if (!*args[1]) {
2675 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2676 file, linenum, args[0]);
2677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680 else if (strcmp(args[1], "mail") == 0) {
2681 const char *res;
2682 unsigned int timeout_mail;
2683 if (!*args[2]) {
2684 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2685 file, linenum, args[0], args[1]);
2686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
2689 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2690 if (res) {
2691 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2692 file, linenum, *res, args[0]);
2693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
2695 }
2696 if (timeout_mail <= 0) {
2697 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
2700 }
2701 curmailers->timeout.mail = timeout_mail;
2702 } else {
2703 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2704 file, linenum, args[0], args[1]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708 }
Simon Horman0d16a402015-01-30 11:22:58 +09002709 else if (*args[0] != 0) {
2710 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714
2715out:
2716 free(errmsg);
2717 return err_code;
2718}
2719
Simon Horman9dc49962015-01-30 11:22:59 +09002720static void free_email_alert(struct proxy *p)
2721{
2722 free(p->email_alert.mailers.name);
2723 p->email_alert.mailers.name = NULL;
2724 free(p->email_alert.from);
2725 p->email_alert.from = NULL;
2726 free(p->email_alert.to);
2727 p->email_alert.to = NULL;
2728 free(p->email_alert.myhostname);
2729 p->email_alert.myhostname = NULL;
2730}
2731
Willy Tarreau3842f002009-06-14 11:39:52 +02002732int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733{
2734 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002735 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002736 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002737 int rc;
2738 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002739 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002740 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002741 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002742 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002743 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002744
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745 if (!strcmp(args[0], "listen"))
2746 rc = PR_CAP_LISTEN;
2747 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002748 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002749 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002750 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002751 else
2752 rc = PR_CAP_NONE;
2753
2754 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 if (!*args[1]) {
2756 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002757 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002759 err_code |= ERR_ALERT | ERR_ABORT;
2760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002762
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002763 err = invalid_char(args[1]);
2764 if (err) {
2765 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2766 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002768 }
2769
Willy Tarreau8f50b682015-05-26 11:45:02 +02002770 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2771 if (curproxy) {
2772 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2773 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2774 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002776 }
2777
Vincent Bernat02779b62016-04-03 13:48:43 +02002778 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_ABORT;
2781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002783
Willy Tarreau97cb7802010-01-03 20:23:58 +01002784 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 curproxy->next = proxy;
2786 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002787 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2788 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002789 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002791 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002792 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793
William Lallemand6e62fb62015-04-28 16:55:23 +02002794 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2795 if (curproxy->cap & PR_CAP_FE)
2796 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 }
2799
2800 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002801 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002802 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002803
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002806 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002807 curproxy->no_options = defproxy.no_options;
2808 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002809 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002810 curproxy->except_net = defproxy.except_net;
2811 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002812 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002813 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002814
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002815 if (defproxy.fwdfor_hdr_len) {
2816 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2817 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2818 }
2819
Willy Tarreaub86db342009-11-30 11:50:16 +01002820 if (defproxy.orgto_hdr_len) {
2821 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2822 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2823 }
2824
Mark Lamourinec2247f02012-01-04 13:02:01 -05002825 if (defproxy.server_id_hdr_len) {
2826 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2827 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2828 }
2829
Willy Tarreau977b8e42006-12-29 14:19:17 +01002830 if (curproxy->cap & PR_CAP_FE) {
2831 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002832 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002833 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002834
2835 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002836 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2837 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002838
2839 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2840 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841
Willy Tarreau977b8e42006-12-29 14:19:17 +01002842 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002843 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002844 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002845 curproxy->fullconn = defproxy.fullconn;
2846 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002847 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002848 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002850 if (defproxy.check_req) {
2851 curproxy->check_req = calloc(1, defproxy.check_len);
2852 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002856 if (defproxy.expect_str) {
2857 curproxy->expect_str = strdup(defproxy.expect_str);
2858 if (defproxy.expect_regex) {
2859 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002860 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2861 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002862 }
2863 }
2864
Willy Tarreau67402132012-05-31 20:40:20 +02002865 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002866 if (defproxy.cookie_name)
2867 curproxy->cookie_name = strdup(defproxy.cookie_name);
2868 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002869 if (defproxy.cookie_domain)
2870 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002871
Willy Tarreau31936852010-10-06 16:59:56 +02002872 if (defproxy.cookie_maxidle)
2873 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2874
2875 if (defproxy.cookie_maxlife)
2876 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2877
Emeric Brun647caf12009-06-30 17:57:00 +02002878 if (defproxy.rdp_cookie_name)
2879 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2880 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2881
Willy Tarreau01732802007-11-01 22:48:15 +01002882 if (defproxy.url_param_name)
2883 curproxy->url_param_name = strdup(defproxy.url_param_name);
2884 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002885
Benoitaffb4812009-03-25 13:02:10 +01002886 if (defproxy.hh_name)
2887 curproxy->hh_name = strdup(defproxy.hh_name);
2888 curproxy->hh_len = defproxy.hh_len;
2889 curproxy->hh_match_domain = defproxy.hh_match_domain;
2890
Willy Tarreauef9a3602012-12-08 22:29:20 +01002891 if (defproxy.conn_src.iface_name)
2892 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2893 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002894 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002895#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002896 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002897#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002898 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002901 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902 if (defproxy.capture_name)
2903 curproxy->capture_name = strdup(defproxy.capture_name);
2904 curproxy->capture_namelen = defproxy.capture_namelen;
2905 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002909 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002910 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002911 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002912 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002913 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002914 curproxy->mon_net = defproxy.mon_net;
2915 curproxy->mon_mask = defproxy.mon_mask;
2916 if (defproxy.monitor_uri)
2917 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2918 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002919 if (defproxy.defbe.name)
2920 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002921
2922 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002923 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2924 if (curproxy->conf.logformat_string &&
2925 curproxy->conf.logformat_string != default_http_log_format &&
2926 curproxy->conf.logformat_string != default_tcp_log_format &&
2927 curproxy->conf.logformat_string != clf_http_log_format)
2928 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2929
2930 if (defproxy.conf.lfs_file) {
2931 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2932 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2933 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002934
2935 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2936 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2937 if (curproxy->conf.logformat_sd_string &&
2938 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2939 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2940
2941 if (defproxy.conf.lfsd_file) {
2942 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2943 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 }
2946
2947 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002948 curproxy->timeout.connect = defproxy.timeout.connect;
2949 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002950 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002951 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002952 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002953 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002954 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002955 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002956 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002957 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002958 }
2959
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002961 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002962
2963 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002964 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002965 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002966 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002967 LIST_INIT(&node->list);
2968 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2969 }
2970
Willy Tarreau62a61232013-04-12 18:13:46 +02002971 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2972 if (curproxy->conf.uniqueid_format_string)
2973 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2974
Dragan Dosen43885c72015-10-01 13:18:13 +02002975 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002976
Willy Tarreau62a61232013-04-12 18:13:46 +02002977 if (defproxy.conf.uif_file) {
2978 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2979 curproxy->conf.uif_line = defproxy.conf.uif_line;
2980 }
William Lallemanda73203e2012-03-12 12:48:57 +01002981
2982 /* copy default header unique id */
2983 if (defproxy.header_unique_id)
2984 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2985
William Lallemand82fe75c2012-10-23 10:25:10 +02002986 /* default compression options */
2987 if (defproxy.comp != NULL) {
2988 curproxy->comp = calloc(1, sizeof(struct comp));
2989 curproxy->comp->algos = defproxy.comp->algos;
2990 curproxy->comp->types = defproxy.comp->types;
2991 }
2992
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002994 curproxy->conf.used_listener_id = EB_ROOT;
2995 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002996
Simon Horman98637e52014-06-20 12:30:16 +09002997 if (defproxy.check_path)
2998 curproxy->check_path = strdup(defproxy.check_path);
2999 if (defproxy.check_command)
3000 curproxy->check_command = strdup(defproxy.check_command);
3001
Simon Horman9dc49962015-01-30 11:22:59 +09003002 if (defproxy.email_alert.mailers.name)
3003 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
3004 if (defproxy.email_alert.from)
3005 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
3006 if (defproxy.email_alert.to)
3007 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
3008 if (defproxy.email_alert.myhostname)
3009 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09003010 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01003011 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09003012
Willy Tarreau93893792009-07-23 13:19:11 +02003013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
3015 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
3016 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003017 /* FIXME-20070101: we should do this too at the end of the
3018 * config parsing to free all default values.
3019 */
William Lallemand6e62fb62015-04-28 16:55:23 +02003020 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
3021 err_code |= ERR_ABORT;
3022 goto out;
3023 }
3024
Willy Tarreaua534fea2008-08-03 12:19:50 +02003025 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003026 free(defproxy.check_command);
3027 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003028 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003029 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003030 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003031 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003032 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003033 free(defproxy.capture_name);
3034 free(defproxy.monitor_uri);
3035 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003036 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003037 free(defproxy.fwdfor_hdr_name);
3038 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003039 free(defproxy.orgto_hdr_name);
3040 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003041 free(defproxy.server_id_hdr_name);
3042 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003043 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003044 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003045 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003046 free(defproxy.expect_regex);
3047 defproxy.expect_regex = NULL;
3048 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003049
Willy Tarreau62a61232013-04-12 18:13:46 +02003050 if (defproxy.conf.logformat_string != default_http_log_format &&
3051 defproxy.conf.logformat_string != default_tcp_log_format &&
3052 defproxy.conf.logformat_string != clf_http_log_format)
3053 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003054
Willy Tarreau62a61232013-04-12 18:13:46 +02003055 free(defproxy.conf.uniqueid_format_string);
3056 free(defproxy.conf.lfs_file);
3057 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003058 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003059 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003060
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003061 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3062 free(defproxy.conf.logformat_sd_string);
3063 free(defproxy.conf.lfsd_file);
3064
Willy Tarreaua534fea2008-08-03 12:19:50 +02003065 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003066 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003067
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 /* we cannot free uri_auth because it might already be used */
3069 init_default_instance();
3070 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003071 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3072 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 }
3076 else if (curproxy == NULL) {
3077 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003081
3082 /* update the current file and line being parsed */
3083 curproxy->conf.args.file = curproxy->conf.file;
3084 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003085
3086 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003087 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3088 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3089 if (err_code & ERR_FATAL)
3090 goto out;
3091 }
3092 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003093 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003094 int cur_arg;
3095
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 if (curproxy == &defproxy) {
3097 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003101 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103
Willy Tarreau24709282013-03-10 21:32:12 +01003104 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003105 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003110
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003111 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003112
3113 /* use default settings for unix sockets */
3114 bind_conf->ux.uid = global.unix_bind.ux.uid;
3115 bind_conf->ux.gid = global.unix_bind.ux.gid;
3116 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003117
3118 /* NOTE: the following line might create several listeners if there
3119 * are comma-separated IPs or port ranges. So all further processing
3120 * will have to be applied to all listeners created after last_listen.
3121 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003122 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3123 if (errmsg && *errmsg) {
3124 indent_msg(&errmsg, 2);
3125 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003126 }
3127 else
3128 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3129 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003133
Willy Tarreau4348fad2012-09-20 16:48:07 +02003134 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3135 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003136 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003137 }
3138
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003139 cur_arg = 2;
3140 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003141 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003142 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003143 char *err;
3144
Willy Tarreau26982662012-09-12 23:17:10 +02003145 kw = bind_find_kw(args[cur_arg]);
3146 if (kw) {
3147 char *err = NULL;
3148 int code;
3149
3150 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003151 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3152 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003153 cur_arg += 1 + kw->skip ;
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157
Willy Tarreau4348fad2012-09-20 16:48:07 +02003158 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003159 err_code |= code;
3160
3161 if (code) {
3162 if (err && *err) {
3163 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003164 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003165 }
3166 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003167 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3168 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003169 if (code & ERR_FATAL) {
3170 free(err);
3171 cur_arg += 1 + kw->skip;
3172 goto out;
3173 }
3174 }
3175 free(err);
3176 cur_arg += 1 + kw->skip;
3177 continue;
3178 }
3179
Willy Tarreau8638f482012-09-18 18:01:17 +02003180 err = NULL;
3181 if (!bind_dumped) {
3182 bind_dump_kws(&err);
3183 indent_msg(&err, 4);
3184 bind_dumped = 1;
3185 }
3186
3187 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3188 file, linenum, args[0], args[1], args[cur_arg],
3189 err ? " Registered keywords :" : "", err ? err : "");
3190 free(err);
3191
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003194 }
Willy Tarreau93893792009-07-23 13:19:11 +02003195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003198 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3200 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003204 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003206
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 /* flush useless bits */
3208 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003211 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003212 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003214
William Lallemanddf1425a2015-04-28 20:17:49 +02003215 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3216 goto out;
3217
Willy Tarreau1c47f852006-07-09 08:22:27 +02003218 if (!*args[1]) {
3219 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003223 }
3224
Willy Tarreaua534fea2008-08-03 12:19:50 +02003225 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003226 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003227 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003228 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003229 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3230
Willy Tarreau93893792009-07-23 13:19:11 +02003231 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003234 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3235 goto out;
3236
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3238 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3239 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3240 else {
3241 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
3245 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003246 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003247 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003248
3249 if (curproxy == &defproxy) {
3250 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3251 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003254 }
3255
William Lallemanddf1425a2015-04-28 20:17:49 +02003256 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3257 goto out;
3258
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003259 if (!*args[1]) {
3260 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3261 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003264 }
3265
3266 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003267 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003268 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003269
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003270 if (curproxy->uuid <= 0) {
3271 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003272 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003275 }
3276
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003277 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3278 if (node) {
3279 struct proxy *target = container_of(node, struct proxy, conf.id);
3280 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3281 file, linenum, proxy_type_str(curproxy), curproxy->id,
3282 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285 }
3286 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003287 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003288 else if (!strcmp(args[0], "description")) {
3289 int i, len=0;
3290 char *d;
3291
Cyril Bonté99ed3272010-01-24 23:29:44 +01003292 if (curproxy == &defproxy) {
3293 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3294 file, linenum, args[0]);
3295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
3297 }
3298
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003299 if (!*args[1]) {
3300 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3301 file, linenum, args[0]);
3302 return -1;
3303 }
3304
Willy Tarreau348acfe2014-04-14 15:00:39 +02003305 for (i = 1; *args[i]; i++)
3306 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003307
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003308 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003309 curproxy->desc = d;
3310
Willy Tarreau348acfe2014-04-14 15:00:39 +02003311 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3312 for (i = 2; *args[i]; i++)
3313 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003314
3315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003317 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 curproxy->state = PR_STSTOPPED;
3320 }
3321 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003322 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 curproxy->state = PR_STNEW;
3325 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003326 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3327 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003328 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003329
3330 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003331 unsigned int low, high;
3332
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003333 if (strcmp(args[cur_arg], "all") == 0) {
3334 set = 0;
3335 break;
3336 }
3337 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003338 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003339 }
3340 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003341 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003342 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003343 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003344 char *dash = strchr(args[cur_arg], '-');
3345
3346 low = high = str2uic(args[cur_arg]);
3347 if (dash)
3348 high = str2uic(dash + 1);
3349
3350 if (high < low) {
3351 unsigned int swap = low;
3352 low = high;
3353 high = swap;
3354 }
3355
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003356 if (low < 1 || high > LONGBITS) {
3357 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3358 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003361 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003362 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003363 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003364 }
3365 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003366 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3367 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003370 }
3371 cur_arg++;
3372 }
3373 curproxy->bind_proc = set;
3374 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003375 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003376 if (curproxy == &defproxy) {
3377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003380 }
3381
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003382 err = invalid_char(args[1]);
3383 if (err) {
3384 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3385 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003387 }
3388
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003389 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003390 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3391 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003394 }
3395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3397 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398
Willy Tarreau977b8e42006-12-29 14:19:17 +01003399 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003401
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 if (*(args[1]) == 0) {
3403 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3404 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003408
Willy Tarreau67402132012-05-31 20:40:20 +02003409 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003410 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003411 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003412 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 curproxy->cookie_name = strdup(args[1]);
3414 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003415
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 cur_arg = 2;
3417 while (*(args[cur_arg])) {
3418 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003419 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 }
3421 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003422 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 }
3424 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003425 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 }
3427 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003428 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 }
3430 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003431 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003433 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003434 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003437 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003439 else if (!strcmp(args[cur_arg], "httponly")) {
3440 curproxy->ck_opts |= PR_CK_HTTPONLY;
3441 }
3442 else if (!strcmp(args[cur_arg], "secure")) {
3443 curproxy->ck_opts |= PR_CK_SECURE;
3444 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003445 else if (!strcmp(args[cur_arg], "domain")) {
3446 if (!*args[cur_arg + 1]) {
3447 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3448 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003451 }
3452
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003453 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003454 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003455 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3456 " dots nor does not start with a dot."
3457 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003458 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003459 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003460 }
3461
3462 err = invalid_domainchar(args[cur_arg + 1]);
3463 if (err) {
3464 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3465 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003468 }
3469
Willy Tarreau68a897b2009-12-03 23:28:34 +01003470 if (!curproxy->cookie_domain) {
3471 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3472 } else {
3473 /* one domain was already specified, add another one by
3474 * building the string which will be returned along with
3475 * the cookie.
3476 */
3477 char *new_ptr;
3478 int new_len = strlen(curproxy->cookie_domain) +
3479 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3480 new_ptr = malloc(new_len);
3481 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3482 free(curproxy->cookie_domain);
3483 curproxy->cookie_domain = new_ptr;
3484 }
Willy Tarreau31936852010-10-06 16:59:56 +02003485 cur_arg++;
3486 }
3487 else if (!strcmp(args[cur_arg], "maxidle")) {
3488 unsigned int maxidle;
3489 const char *res;
3490
3491 if (!*args[cur_arg + 1]) {
3492 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3493 file, linenum, args[cur_arg]);
3494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
3496 }
3497
3498 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3499 if (res) {
3500 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3501 file, linenum, *res, args[cur_arg]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
3505 curproxy->cookie_maxidle = maxidle;
3506 cur_arg++;
3507 }
3508 else if (!strcmp(args[cur_arg], "maxlife")) {
3509 unsigned int maxlife;
3510 const char *res;
3511
3512 if (!*args[cur_arg + 1]) {
3513 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3514 file, linenum, args[cur_arg]);
3515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
3517 }
3518
3519 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3520 if (res) {
3521 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3522 file, linenum, *res, args[cur_arg]);
3523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
3525 }
3526 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003527 cur_arg++;
3528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003530 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 }
3535 cur_arg++;
3536 }
Willy Tarreau67402132012-05-31 20:40:20 +02003537 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3539 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 }
3542
Willy Tarreau67402132012-05-31 20:40:20 +02003543 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3545 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003548
Willy Tarreau67402132012-05-31 20:40:20 +02003549 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003550 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3551 file, linenum);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003555 else if (!strcmp(args[0], "email-alert")) {
3556 if (*(args[1]) == 0) {
3557 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3558 file, linenum, args[0]);
3559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
3561 }
3562
3563 if (!strcmp(args[1], "from")) {
3564 if (*(args[1]) == 0) {
3565 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3566 file, linenum, args[1]);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
3570 free(curproxy->email_alert.from);
3571 curproxy->email_alert.from = strdup(args[2]);
3572 }
3573 else if (!strcmp(args[1], "mailers")) {
3574 if (*(args[1]) == 0) {
3575 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3576 file, linenum, args[1]);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
3580 free(curproxy->email_alert.mailers.name);
3581 curproxy->email_alert.mailers.name = strdup(args[2]);
3582 }
3583 else if (!strcmp(args[1], "myhostname")) {
3584 if (*(args[1]) == 0) {
3585 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3586 file, linenum, args[1]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590 free(curproxy->email_alert.myhostname);
3591 curproxy->email_alert.myhostname = strdup(args[2]);
3592 }
Simon Horman64e34162015-02-06 11:11:57 +09003593 else if (!strcmp(args[1], "level")) {
3594 curproxy->email_alert.level = get_log_level(args[2]);
3595 if (curproxy->email_alert.level < 0) {
3596 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3597 file, linenum, args[1], args[2]);
3598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
3600 }
3601 }
Simon Horman9dc49962015-01-30 11:22:59 +09003602 else if (!strcmp(args[1], "to")) {
3603 if (*(args[1]) == 0) {
3604 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3605 file, linenum, args[1]);
3606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
3608 }
3609 free(curproxy->email_alert.to);
3610 curproxy->email_alert.to = strdup(args[2]);
3611 }
3612 else {
3613 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3614 file, linenum, args[1]);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
3617 }
Simon Horman64e34162015-02-06 11:11:57 +09003618 /* Indicate that the email_alert is at least partially configured */
3619 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003620 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003621 else if (!strcmp(args[0], "external-check")) {
3622 if (*(args[1]) == 0) {
3623 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3624 file, linenum, args[0]);
3625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
3627 }
3628
3629 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003630 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003631 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003632 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003633 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3634 file, linenum, args[1]);
3635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
3637 }
3638 free(curproxy->check_command);
3639 curproxy->check_command = strdup(args[2]);
3640 }
3641 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003642 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003643 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003644 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003645 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3646 file, linenum, args[1]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650 free(curproxy->check_path);
3651 curproxy->check_path = strdup(args[2]);
3652 }
3653 else {
3654 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3655 file, linenum, args[1]);
3656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
3658 }
3659 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003660 else if (!strcmp(args[0], "persist")) { /* persist */
3661 if (*(args[1]) == 0) {
3662 Alert("parsing [%s:%d] : missing persist method.\n",
3663 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003666 }
3667
3668 if (!strncmp(args[1], "rdp-cookie", 10)) {
3669 curproxy->options2 |= PR_O2_RDPC_PRST;
3670
Emeric Brunb982a3d2010-01-04 15:45:53 +01003671 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003672 const char *beg, *end;
3673
3674 beg = args[1] + 11;
3675 end = strchr(beg, ')');
3676
William Lallemanddf1425a2015-04-28 20:17:49 +02003677 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3678 goto out;
3679
Emeric Brun647caf12009-06-30 17:57:00 +02003680 if (!end || end == beg) {
3681 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3682 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003685 }
3686
3687 free(curproxy->rdp_cookie_name);
3688 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3689 curproxy->rdp_cookie_len = end-beg;
3690 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003691 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003692 free(curproxy->rdp_cookie_name);
3693 curproxy->rdp_cookie_name = strdup("msts");
3694 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3695 }
3696 else { /* syntax */
3697 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3698 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003701 }
3702 }
3703 else {
3704 Alert("parsing [%s:%d] : unknown persist method.\n",
3705 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003708 }
3709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003711 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003715 else if (!strcmp(args[0], "load-server-state-from-file")) {
3716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3717 err_code |= ERR_WARN;
3718 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3719 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3720 }
3721 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3722 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3723 }
3724 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3725 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3726 }
3727 else {
3728 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3729 file, linenum, args[0], args[1]);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733 }
3734 else if (!strcmp(args[0], "server-state-file-name")) {
3735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3736 err_code |= ERR_WARN;
3737 if (*(args[1]) == 0) {
3738 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3739 file, linenum, args[0]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743 else if (!strcmp(args[1], "use-backend-name"))
3744 curproxy->server_state_file_name = strdup(curproxy->id);
3745 else
3746 curproxy->server_state_file_name = strdup(args[1]);
3747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003751
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003753 if (curproxy == &defproxy) {
3754 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
3757 }
3758
William Lallemand1a748ae2015-05-19 16:37:23 +02003759 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3760 goto out;
3761
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 if (*(args[4]) == 0) {
3763 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3764 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003768 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 curproxy->capture_name = strdup(args[2]);
3770 curproxy->capture_namelen = strlen(curproxy->capture_name);
3771 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 curproxy->to_log |= LW_COOKIE;
3773 }
3774 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3775 struct cap_hdr *hdr;
3776
3777 if (curproxy == &defproxy) {
3778 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
3782
William Lallemand1a748ae2015-05-19 16:37:23 +02003783 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3784 goto out;
3785
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3787 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3788 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 }
3792
Vincent Bernat02779b62016-04-03 13:48:43 +02003793 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 hdr->next = curproxy->req_cap;
3795 hdr->name = strdup(args[3]);
3796 hdr->namelen = strlen(args[3]);
3797 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003798 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 hdr->index = curproxy->nb_req_cap++;
3800 curproxy->req_cap = hdr;
3801 curproxy->to_log |= LW_REQHDR;
3802 }
3803 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3804 struct cap_hdr *hdr;
3805
3806 if (curproxy == &defproxy) {
3807 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
3811
William Lallemand1a748ae2015-05-19 16:37:23 +02003812 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3813 goto out;
3814
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3816 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3817 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003821 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 hdr->next = curproxy->rsp_cap;
3823 hdr->name = strdup(args[3]);
3824 hdr->namelen = strlen(args[3]);
3825 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003826 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 hdr->index = curproxy->nb_rsp_cap++;
3828 curproxy->rsp_cap = hdr;
3829 curproxy->to_log |= LW_RSPHDR;
3830 }
3831 else {
3832 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3833 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 }
3837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003839 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003841
William Lallemanddf1425a2015-04-28 20:17:49 +02003842 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3843 goto out;
3844
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 if (*(args[1]) == 0) {
3846 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3847 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
3851 curproxy->conn_retries = atol(args[1]);
3852 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003853 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003854 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003855
3856 if (curproxy == &defproxy) {
3857 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861
Willy Tarreau20b0de52012-12-24 15:45:22 +01003862 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003863 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003864 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3865 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3866 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3867 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003868 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003869 file, linenum, args[0]);
3870 err_code |= ERR_WARN;
3871 }
3872
Willy Tarreauff011f22011-01-06 17:51:27 +01003873 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003874
Willy Tarreauff011f22011-01-06 17:51:27 +01003875 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003876 err_code |= ERR_ALERT | ERR_ABORT;
3877 goto out;
3878 }
3879
Willy Tarreau5002f572014-04-23 01:32:02 +02003880 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003881 err_code |= warnif_cond_conflicts(rule->cond,
3882 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3883 file, linenum);
3884
Willy Tarreauff011f22011-01-06 17:51:27 +01003885 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003886 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003887 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003888 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003889
3890 if (curproxy == &defproxy) {
3891 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
3896 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003897 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003898 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3899 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003900 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3901 file, linenum, args[0]);
3902 err_code |= ERR_WARN;
3903 }
3904
3905 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3906
3907 if (!rule) {
3908 err_code |= ERR_ALERT | ERR_ABORT;
3909 goto out;
3910 }
3911
3912 err_code |= warnif_cond_conflicts(rule->cond,
3913 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3914 file, linenum);
3915
3916 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3917 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003918 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3919 /* set the header name and length into the proxy structure */
3920 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3921 err_code |= ERR_WARN;
3922
3923 if (!*args[1]) {
3924 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3925 file, linenum, args[0]);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929
3930 /* set the desired header name */
3931 free(curproxy->server_id_hdr_name);
3932 curproxy->server_id_hdr_name = strdup(args[1]);
3933 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3934 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003935 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003936 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003937
Willy Tarreaub099aca2008-10-12 17:26:37 +02003938 if (curproxy == &defproxy) {
3939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003942 }
3943
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003944 /* emulate "block" using "http-request block". Since these rules are supposed to
3945 * be processed before all http-request rules, we put them into their own list
3946 * and will insert them at the end.
3947 */
3948 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3949 if (!rule) {
3950 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003951 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003952 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003953 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3954 err_code |= warnif_cond_conflicts(rule->cond,
3955 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3956 file, linenum);
3957 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003958
3959 if (!already_warned(WARN_BLOCK_DEPRECATED))
3960 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of 'http-request deny' which uses the exact same syntax. The rules are translated but support might disappear in a future version.\n", file, linenum, args[0]);
3961
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003962 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003963 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003964 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003965
Cyril Bonté99ed3272010-01-24 23:29:44 +01003966 if (curproxy == &defproxy) {
3967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
3971
Willy Tarreaube4653b2015-05-28 15:26:58 +02003972 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003973 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3974 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003977 }
3978
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003979 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003980 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003981 err_code |= warnif_cond_conflicts(rule->cond,
3982 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3983 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003984 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003985 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003986 struct switching_rule *rule;
3987
Willy Tarreaub099aca2008-10-12 17:26:37 +02003988 if (curproxy == &defproxy) {
3989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003992 }
3993
Willy Tarreau55ea7572007-06-17 19:56:27 +02003994 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003996
3997 if (*(args[1]) == 0) {
3998 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004001 }
4002
Willy Tarreauf51658d2014-04-23 01:21:56 +02004003 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
4004 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4005 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4006 file, linenum, errmsg);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004010
Willy Tarreauf51658d2014-04-23 01:21:56 +02004011 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004012 }
4013
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004014 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01004015 if (!rule) {
4016 Alert("Out of memory error.\n");
4017 goto out;
4018 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004019 rule->cond = cond;
4020 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01004021 rule->line = linenum;
4022 rule->file = strdup(file);
4023 if (!rule->file) {
4024 Alert("Out of memory error.\n");
4025 goto out;
4026 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004027 LIST_INIT(&rule->list);
4028 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4029 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004030 else if (strcmp(args[0], "use-server") == 0) {
4031 struct server_rule *rule;
4032
4033 if (curproxy == &defproxy) {
4034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
4038
4039 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4040 err_code |= ERR_WARN;
4041
4042 if (*(args[1]) == 0) {
4043 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047
4048 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4049 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4050 file, linenum, args[0]);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004055 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4056 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4057 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004062 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004063
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004064 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004065 rule->cond = cond;
4066 rule->srv.name = strdup(args[1]);
4067 LIST_INIT(&rule->list);
4068 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4069 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4070 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004071 else if ((!strcmp(args[0], "force-persist")) ||
4072 (!strcmp(args[0], "ignore-persist"))) {
4073 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004074
4075 if (curproxy == &defproxy) {
4076 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080
4081 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4082 err_code |= ERR_WARN;
4083
Willy Tarreauef6494c2010-01-28 17:12:36 +01004084 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004085 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4086 file, linenum, args[0]);
4087 err_code |= ERR_ALERT | ERR_FATAL;
4088 goto out;
4089 }
4090
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004091 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4092 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4093 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
4097
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004098 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4099 * where force-persist is applied.
4100 */
4101 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004102
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004103 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004104 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004105 if (!strcmp(args[0], "force-persist")) {
4106 rule->type = PERSIST_TYPE_FORCE;
4107 } else {
4108 rule->type = PERSIST_TYPE_IGNORE;
4109 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004110 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004111 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004112 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113 else if (!strcmp(args[0], "stick-table")) {
4114 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004115 struct proxy *other;
4116
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004117 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004118 if (other) {
4119 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4120 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
4123 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124
Emeric Brun32da3c42010-09-23 18:39:19 +02004125 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004126 curproxy->table.type = (unsigned int)-1;
4127 while (*args[myidx]) {
4128 const char *err;
4129
4130 if (strcmp(args[myidx], "size") == 0) {
4131 myidx++;
4132 if (!*(args[myidx])) {
4133 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4134 file, linenum, args[myidx-1]);
4135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
4137 }
4138 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
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 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004144 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004145 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004146 else if (strcmp(args[myidx], "peers") == 0) {
4147 myidx++;
Godbach50523162013-12-11 19:48:57 +08004148 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004149 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4150 file, linenum, args[myidx-1]);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Godbach50523162013-12-11 19:48:57 +08004153 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004154 curproxy->table.peers.name = strdup(args[myidx++]);
4155 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 else if (strcmp(args[myidx], "expire") == 0) {
4157 myidx++;
4158 if (!*(args[myidx])) {
4159 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4160 file, linenum, args[myidx-1]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4165 if (err) {
4166 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4167 file, linenum, *err, args[myidx-1]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004171 if (val > INT_MAX) {
4172 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4173 file, linenum, val);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004177 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004178 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004179 }
4180 else if (strcmp(args[myidx], "nopurge") == 0) {
4181 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004182 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004183 }
4184 else if (strcmp(args[myidx], "type") == 0) {
4185 myidx++;
4186 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4187 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4188 file, linenum, args[myidx]);
4189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
4191 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004192 /* myidx already points to next arg */
4193 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004194 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004195 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004196 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004197
4198 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004199 nw = args[myidx];
4200 while (*nw) {
4201 /* the "store" keyword supports a comma-separated list */
4202 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004203 sa = NULL; /* store arg */
4204 while (*nw && *nw != ',') {
4205 if (*nw == '(') {
4206 *nw = 0;
4207 sa = ++nw;
4208 while (*nw != ')') {
4209 if (!*nw) {
4210 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4211 file, linenum, args[0], cw);
4212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
4214 }
4215 nw++;
4216 }
4217 *nw = '\0';
4218 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004219 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004220 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004221 if (*nw)
4222 *nw++ = '\0';
4223 type = stktable_get_data_type(cw);
4224 if (type < 0) {
4225 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4226 file, linenum, args[0], cw);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
Willy Tarreauac782882010-06-20 10:41:54 +02004230
4231 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4232 switch (err) {
4233 case PE_NONE: break;
4234 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004235 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4236 file, linenum, args[0], cw);
4237 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004238 break;
4239
4240 case PE_ARG_MISSING:
4241 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4242 file, linenum, args[0], cw);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
4245
4246 case PE_ARG_NOT_USED:
4247 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4248 file, linenum, args[0], cw);
4249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251
4252 default:
4253 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4254 file, linenum, args[0], cw);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004257 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004258 }
4259 myidx++;
4260 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004261 else {
4262 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4263 file, linenum, args[myidx]);
4264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004266 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004267 }
4268
4269 if (!curproxy->table.size) {
4270 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4271 file, linenum);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275
4276 if (curproxy->table.type == (unsigned int)-1) {
4277 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4278 file, linenum);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
4282 }
4283 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004284 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004285 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004286 int myidx = 0;
4287 const char *name = NULL;
4288 int flags;
4289
4290 if (curproxy == &defproxy) {
4291 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
4294 }
4295
4296 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4297 err_code |= ERR_WARN;
4298 goto out;
4299 }
4300
4301 myidx++;
4302 if ((strcmp(args[myidx], "store") == 0) ||
4303 (strcmp(args[myidx], "store-request") == 0)) {
4304 myidx++;
4305 flags = STK_IS_STORE;
4306 }
4307 else if (strcmp(args[myidx], "store-response") == 0) {
4308 myidx++;
4309 flags = STK_IS_STORE | STK_ON_RSP;
4310 }
4311 else if (strcmp(args[myidx], "match") == 0) {
4312 myidx++;
4313 flags = STK_IS_MATCH;
4314 }
4315 else if (strcmp(args[myidx], "on") == 0) {
4316 myidx++;
4317 flags = STK_IS_MATCH | STK_IS_STORE;
4318 }
4319 else {
4320 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324
4325 if (*(args[myidx]) == 0) {
4326 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004331 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004332 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004333 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004334 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
4337 }
4338
4339 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004340 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4341 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4342 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004343 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004344 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004345 goto out;
4346 }
4347 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004348 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4349 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4350 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004351 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004352 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004353 goto out;
4354 }
4355 }
4356
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004357 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004358 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004359
Emeric Brunb982a3d2010-01-04 15:45:53 +01004360 if (strcmp(args[myidx], "table") == 0) {
4361 myidx++;
4362 name = args[myidx++];
4363 }
4364
Willy Tarreauef6494c2010-01-28 17:12:36 +01004365 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004366 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4367 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4368 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004369 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004370 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004371 goto out;
4372 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004373 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004374 else if (*(args[myidx])) {
4375 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4376 file, linenum, args[0], args[myidx]);
4377 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004378 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004379 goto out;
4380 }
Emeric Brun97679e72010-09-23 17:56:44 +02004381 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004382 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004383 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004384 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004385
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004386 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004387 rule->cond = cond;
4388 rule->expr = expr;
4389 rule->flags = flags;
4390 rule->table.name = name ? strdup(name) : NULL;
4391 LIST_INIT(&rule->list);
4392 if (flags & STK_ON_RSP)
4393 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4394 else
4395 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4396 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 else if (!strcmp(args[0], "stats")) {
4398 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4399 curproxy->uri_auth = NULL; /* we must detach from the default config */
4400
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004401 if (!*args[1]) {
4402 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004403 } else if (!strcmp(args[1], "admin")) {
4404 struct stats_admin_rule *rule;
4405
4406 if (curproxy == &defproxy) {
4407 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
4410 }
4411
4412 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4413 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4414 err_code |= ERR_ALERT | ERR_ABORT;
4415 goto out;
4416 }
4417
4418 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4419 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4420 file, linenum, args[0], args[1]);
4421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
4423 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004424 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4425 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4426 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
4429 }
4430
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004431 err_code |= warnif_cond_conflicts(cond,
4432 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4433 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004434
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004435 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004436 rule->cond = cond;
4437 LIST_INIT(&rule->list);
4438 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 } else if (!strcmp(args[1], "uri")) {
4440 if (*(args[2]) == 0) {
4441 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4445 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_ABORT;
4447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
4449 } else if (!strcmp(args[1], "realm")) {
4450 if (*(args[2]) == 0) {
4451 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4455 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_ABORT;
4457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004458 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004459 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004460 unsigned interval;
4461
4462 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4463 if (err) {
4464 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4465 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004468 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4469 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_ABORT;
4471 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004472 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004473 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004474 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004475
4476 if (curproxy == &defproxy) {
4477 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
4480 }
4481
4482 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4483 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4484 err_code |= ERR_ALERT | ERR_ABORT;
4485 goto out;
4486 }
4487
Willy Tarreauff011f22011-01-06 17:51:27 +01004488 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004489 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004490 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4491 file, linenum, args[0]);
4492 err_code |= ERR_WARN;
4493 }
4494
Willy Tarreauff011f22011-01-06 17:51:27 +01004495 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004496
Willy Tarreauff011f22011-01-06 17:51:27 +01004497 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004498 err_code |= ERR_ALERT | ERR_ABORT;
4499 goto out;
4500 }
4501
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004502 err_code |= warnif_cond_conflicts(rule->cond,
4503 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4504 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004505 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004506
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 } else if (!strcmp(args[1], "auth")) {
4508 if (*(args[2]) == 0) {
4509 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4513 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004514 err_code |= ERR_ALERT | ERR_ABORT;
4515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 }
4517 } else if (!strcmp(args[1], "scope")) {
4518 if (*(args[2]) == 0) {
4519 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4523 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_ABORT;
4525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 }
4527 } else if (!strcmp(args[1], "enable")) {
4528 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4529 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_ALERT | ERR_ABORT;
4531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004533 } else if (!strcmp(args[1], "hide-version")) {
4534 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4535 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_ABORT;
4537 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004538 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004539 } else if (!strcmp(args[1], "show-legends")) {
4540 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4541 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4542 err_code |= ERR_ALERT | ERR_ABORT;
4543 goto out;
4544 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004545 } else if (!strcmp(args[1], "show-node")) {
4546
4547 if (*args[2]) {
4548 int i;
4549 char c;
4550
4551 for (i=0; args[2][i]; i++) {
4552 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004553 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4554 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004555 break;
4556 }
4557
4558 if (!i || args[2][i]) {
4559 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4560 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4561 file, linenum, args[0], args[1]);
4562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
4564 }
4565 }
4566
4567 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4568 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4569 err_code |= ERR_ALERT | ERR_ABORT;
4570 goto out;
4571 }
4572 } else if (!strcmp(args[1], "show-desc")) {
4573 char *desc = NULL;
4574
4575 if (*args[2]) {
4576 int i, len=0;
4577 char *d;
4578
Willy Tarreau348acfe2014-04-14 15:00:39 +02004579 for (i = 2; *args[i]; i++)
4580 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004581
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004582 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004583
Willy Tarreau348acfe2014-04-14 15:00:39 +02004584 d += snprintf(d, desc + len - d, "%s", args[2]);
4585 for (i = 3; *args[i]; i++)
4586 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004587 }
4588
4589 if (!*args[2] && !global.desc)
4590 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4591 file, linenum, args[1]);
4592 else {
4593 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4594 free(desc);
4595 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4596 err_code |= ERR_ALERT | ERR_ABORT;
4597 goto out;
4598 }
4599 free(desc);
4600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004602stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004603 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 +01004604 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 }
4608 }
4609 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004610 int optnum;
4611
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004612 if (*(args[1]) == '\0') {
4613 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4614 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004618
4619 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4620 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004621 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4622 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4623 file, linenum, cfg_opts[optnum].name);
4624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
4626 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004627 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4628 goto out;
4629
Willy Tarreau93893792009-07-23 13:19:11 +02004630 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4631 err_code |= ERR_WARN;
4632 goto out;
4633 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004634
Willy Tarreau3842f002009-06-14 11:39:52 +02004635 curproxy->no_options &= ~cfg_opts[optnum].val;
4636 curproxy->options &= ~cfg_opts[optnum].val;
4637
4638 switch (kwm) {
4639 case KWM_STD:
4640 curproxy->options |= cfg_opts[optnum].val;
4641 break;
4642 case KWM_NO:
4643 curproxy->no_options |= cfg_opts[optnum].val;
4644 break;
4645 case KWM_DEF: /* already cleared */
4646 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004647 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004648
Willy Tarreau93893792009-07-23 13:19:11 +02004649 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004650 }
4651 }
4652
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004653 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4654 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004655 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4656 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4657 file, linenum, cfg_opts2[optnum].name);
4658 err_code |= ERR_ALERT | ERR_FATAL;
4659 goto out;
4660 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004661 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4662 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004663 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4664 err_code |= ERR_WARN;
4665 goto out;
4666 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004667
Willy Tarreau3842f002009-06-14 11:39:52 +02004668 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4669 curproxy->options2 &= ~cfg_opts2[optnum].val;
4670
4671 switch (kwm) {
4672 case KWM_STD:
4673 curproxy->options2 |= cfg_opts2[optnum].val;
4674 break;
4675 case KWM_NO:
4676 curproxy->no_options2 |= cfg_opts2[optnum].val;
4677 break;
4678 case KWM_DEF: /* already cleared */
4679 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004680 }
Willy Tarreau93893792009-07-23 13:19:11 +02004681 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004682 }
4683 }
4684
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004685 /* HTTP options override each other. They can be cancelled using
4686 * "no option xxx" which only switches to default mode if the mode
4687 * was this one (useful for cancelling options set in defaults
4688 * sections).
4689 */
4690 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004691 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4692 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004693 if (kwm == KWM_STD) {
4694 curproxy->options &= ~PR_O_HTTP_MODE;
4695 curproxy->options |= PR_O_HTTP_PCL;
4696 goto out;
4697 }
4698 else if (kwm == KWM_NO) {
4699 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4700 curproxy->options &= ~PR_O_HTTP_MODE;
4701 goto out;
4702 }
4703 }
4704 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004705 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4706 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004707 if (kwm == KWM_STD) {
4708 curproxy->options &= ~PR_O_HTTP_MODE;
4709 curproxy->options |= PR_O_HTTP_FCL;
4710 goto out;
4711 }
4712 else if (kwm == KWM_NO) {
4713 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4714 curproxy->options &= ~PR_O_HTTP_MODE;
4715 goto out;
4716 }
4717 }
4718 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004719 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4720 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004721 if (kwm == KWM_STD) {
4722 curproxy->options &= ~PR_O_HTTP_MODE;
4723 curproxy->options |= PR_O_HTTP_SCL;
4724 goto out;
4725 }
4726 else if (kwm == KWM_NO) {
4727 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4728 curproxy->options &= ~PR_O_HTTP_MODE;
4729 goto out;
4730 }
4731 }
4732 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004733 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4734 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004735 if (kwm == KWM_STD) {
4736 curproxy->options &= ~PR_O_HTTP_MODE;
4737 curproxy->options |= PR_O_HTTP_KAL;
4738 goto out;
4739 }
4740 else if (kwm == KWM_NO) {
4741 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4742 curproxy->options &= ~PR_O_HTTP_MODE;
4743 goto out;
4744 }
4745 }
4746 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004747 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4748 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004749 if (kwm == KWM_STD) {
4750 curproxy->options &= ~PR_O_HTTP_MODE;
4751 curproxy->options |= PR_O_HTTP_TUN;
4752 goto out;
4753 }
4754 else if (kwm == KWM_NO) {
4755 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4756 curproxy->options &= ~PR_O_HTTP_MODE;
4757 goto out;
4758 }
4759 }
4760
Joseph Lynch726ab712015-05-11 23:25:34 -07004761 /* Redispatch can take an integer argument that control when the
4762 * resispatch occurs. All values are relative to the retries option.
4763 * This can be cancelled using "no option xxx".
4764 */
4765 if (strcmp(args[1], "redispatch") == 0) {
4766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4767 err_code |= ERR_WARN;
4768 goto out;
4769 }
4770
4771 curproxy->no_options &= ~PR_O_REDISP;
4772 curproxy->options &= ~PR_O_REDISP;
4773
4774 switch (kwm) {
4775 case KWM_STD:
4776 curproxy->options |= PR_O_REDISP;
4777 curproxy->redispatch_after = -1;
4778 if(*args[2]) {
4779 curproxy->redispatch_after = atol(args[2]);
4780 }
4781 break;
4782 case KWM_NO:
4783 curproxy->no_options |= PR_O_REDISP;
4784 curproxy->redispatch_after = 0;
4785 break;
4786 case KWM_DEF: /* already cleared */
4787 break;
4788 }
4789 goto out;
4790 }
4791
Willy Tarreau3842f002009-06-14 11:39:52 +02004792 if (kwm != KWM_STD) {
4793 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004794 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004797 }
4798
Emeric Brun3a058f32009-06-30 18:26:00 +02004799 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004800 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004802 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004803 if (*(args[2]) != '\0') {
4804 if (!strcmp(args[2], "clf")) {
4805 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004806 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004807 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004808 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004811 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004812 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4813 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004814 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004815 if (curproxy->conf.logformat_string != default_http_log_format &&
4816 curproxy->conf.logformat_string != default_tcp_log_format &&
4817 curproxy->conf.logformat_string != clf_http_log_format)
4818 free(curproxy->conf.logformat_string);
4819 curproxy->conf.logformat_string = logformat;
4820
4821 free(curproxy->conf.lfs_file);
4822 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4823 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004824 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004825 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004827 if (curproxy->conf.logformat_string != default_http_log_format &&
4828 curproxy->conf.logformat_string != default_tcp_log_format &&
4829 curproxy->conf.logformat_string != clf_http_log_format)
4830 free(curproxy->conf.logformat_string);
4831 curproxy->conf.logformat_string = default_tcp_log_format;
4832
4833 free(curproxy->conf.lfs_file);
4834 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4835 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004836
4837 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4838 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004841 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004842 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004843 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004844
William Lallemanddf1425a2015-04-28 20:17:49 +02004845 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4846 goto out;
4847
Willy Tarreau13943ab2006-12-31 00:24:10 +01004848 if (curproxy->cap & PR_CAP_FE)
4849 curproxy->options |= PR_O_TCP_CLI_KA;
4850 if (curproxy->cap & PR_CAP_BE)
4851 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 }
4853 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004855 err_code |= ERR_WARN;
4856
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004858 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004859 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004860 curproxy->options2 &= ~PR_O2_CHK_ANY;
4861 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 if (!*args[2]) { /* no argument */
4863 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4864 curproxy->check_len = strlen(DEF_CHECK_REQ);
4865 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004866 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004867 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004869 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004871 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 if (*args[4])
4873 reqlen += strlen(args[4]);
4874 else
4875 reqlen += strlen("HTTP/1.0");
4876
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004877 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004879 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004881 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4882 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004883 }
4884 else if (!strcmp(args[1], "ssl-hello-chk")) {
4885 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004886 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004887 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004888
Willy Tarreaua534fea2008-08-03 12:19:50 +02004889 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004890 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004891 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004892 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004893
4894 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 }
Willy Tarreau23677902007-05-08 23:50:35 +02004897 else if (!strcmp(args[1], "smtpchk")) {
4898 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004899 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004900 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004901 curproxy->options2 &= ~PR_O2_CHK_ANY;
4902 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004903
4904 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4905 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4906 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4907 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4908 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4909 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004910 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004911 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4912 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4913 } else {
4914 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4915 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4916 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4917 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4918 }
4919 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004920 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4921 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004922 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004923 else if (!strcmp(args[1], "pgsql-check")) {
4924 /* use PostgreSQL request to check servers' health */
4925 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4926 err_code |= ERR_WARN;
4927
4928 free(curproxy->check_req);
4929 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004930 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004931 curproxy->options2 |= PR_O2_PGSQL_CHK;
4932
4933 if (*(args[2])) {
4934 int cur_arg = 2;
4935
4936 while (*(args[cur_arg])) {
4937 if (strcmp(args[cur_arg], "user") == 0) {
4938 char * packet;
4939 uint32_t packet_len;
4940 uint32_t pv;
4941
4942 /* suboption header - needs additional argument for it */
4943 if (*(args[cur_arg+1]) == 0) {
4944 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4945 file, linenum, args[0], args[1], args[cur_arg]);
4946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
4949
4950 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4951 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4952 pv = htonl(0x30000); /* protocol version 3.0 */
4953
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004954 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004955
4956 memcpy(packet + 4, &pv, 4);
4957
4958 /* copy "user" */
4959 memcpy(packet + 8, "user", 4);
4960
4961 /* copy username */
4962 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4963
4964 free(curproxy->check_req);
4965 curproxy->check_req = packet;
4966 curproxy->check_len = packet_len;
4967
4968 packet_len = htonl(packet_len);
4969 memcpy(packet, &packet_len, 4);
4970 cur_arg += 2;
4971 } else {
4972 /* unknown suboption - catchall */
4973 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4974 file, linenum, args[0], args[1]);
4975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
4977 }
4978 } /* end while loop */
4979 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004980 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4981 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004982 }
4983
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004984 else if (!strcmp(args[1], "redis-check")) {
4985 /* use REDIS PING request to check servers' health */
4986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4987 err_code |= ERR_WARN;
4988
4989 free(curproxy->check_req);
4990 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004991 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004992 curproxy->options2 |= PR_O2_REDIS_CHK;
4993
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004994 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004995 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4996 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004997
4998 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4999 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02005000 }
5001
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005002 else if (!strcmp(args[1], "mysql-check")) {
5003 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005004 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5005 err_code |= ERR_WARN;
5006
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005007 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01005008 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005009 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005010 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005011
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005012 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005013 * const char mysql40_client_auth_pkt[] = {
5014 * "\x0e\x00\x00" // packet length
5015 * "\x01" // packet number
5016 * "\x00\x00" // client capabilities
5017 * "\x00\x00\x01" // max packet
5018 * "haproxy\x00" // username (null terminated string)
5019 * "\x00" // filler (always 0x00)
5020 * "\x01\x00\x00" // packet length
5021 * "\x00" // packet number
5022 * "\x01" // COM_QUIT command
5023 * };
5024 */
5025
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005026 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5027 * const char mysql41_client_auth_pkt[] = {
5028 * "\x0e\x00\x00\" // packet length
5029 * "\x01" // packet number
5030 * "\x00\x00\x00\x00" // client capabilities
5031 * "\x00\x00\x00\x01" // max packet
5032 * "\x21" // character set (UTF-8)
5033 * char[23] // All zeroes
5034 * "haproxy\x00" // username (null terminated string)
5035 * "\x00" // filler (always 0x00)
5036 * "\x01\x00\x00" // packet length
5037 * "\x00" // packet number
5038 * "\x01" // COM_QUIT command
5039 * };
5040 */
5041
5042
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005043 if (*(args[2])) {
5044 int cur_arg = 2;
5045
5046 while (*(args[cur_arg])) {
5047 if (strcmp(args[cur_arg], "user") == 0) {
5048 char *mysqluser;
5049 int packetlen, reqlen, userlen;
5050
5051 /* suboption header - needs additional argument for it */
5052 if (*(args[cur_arg+1]) == 0) {
5053 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5054 file, linenum, args[0], args[1], args[cur_arg]);
5055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
5057 }
5058 mysqluser = args[cur_arg + 1];
5059 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005060
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005061 if (*(args[cur_arg+2])) {
5062 if (!strcmp(args[cur_arg+2], "post-41")) {
5063 packetlen = userlen + 7 + 27;
5064 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005065
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005066 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005067 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005068 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005069
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005070 snprintf(curproxy->check_req, 4, "%c%c%c",
5071 ((unsigned char) packetlen & 0xff),
5072 ((unsigned char) (packetlen >> 8) & 0xff),
5073 ((unsigned char) (packetlen >> 16) & 0xff));
5074
5075 curproxy->check_req[3] = 1;
5076 curproxy->check_req[5] = 130;
5077 curproxy->check_req[11] = 1;
5078 curproxy->check_req[12] = 33;
5079 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5080 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5081 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5082 cur_arg += 3;
5083 } else {
5084 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
5088 } else {
5089 packetlen = userlen + 7;
5090 reqlen = packetlen + 9;
5091
5092 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005093 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005094 curproxy->check_len = reqlen;
5095
5096 snprintf(curproxy->check_req, 4, "%c%c%c",
5097 ((unsigned char) packetlen & 0xff),
5098 ((unsigned char) (packetlen >> 8) & 0xff),
5099 ((unsigned char) (packetlen >> 16) & 0xff));
5100
5101 curproxy->check_req[3] = 1;
5102 curproxy->check_req[5] = 128;
5103 curproxy->check_req[8] = 1;
5104 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5105 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5106 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5107 cur_arg += 2;
5108 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005109 } else {
5110 /* unknown suboption - catchall */
5111 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5112 file, linenum, args[0], args[1]);
5113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
5115 }
5116 } /* end while loop */
5117 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005118 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005119 else if (!strcmp(args[1], "ldap-check")) {
5120 /* use LDAP request to check servers' health */
5121 free(curproxy->check_req);
5122 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005123 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005124 curproxy->options2 |= PR_O2_LDAP_CHK;
5125
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005126 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005127 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5128 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005129 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5130 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005131 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01005132 else if (!strcmp(args[1], "spop-check")) {
5133 if (curproxy == &defproxy) {
5134 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
5135 file, linenum, args[0], args[1]);
5136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
5138 }
5139 if (curproxy->cap & PR_CAP_FE) {
5140 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
5141 file, linenum, args[0], args[1]);
5142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
5144 }
5145
5146 /* use SPOE request 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_SPOP_CHK;
5151
5152 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
5153 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
5156 }
5157 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5158 goto out;
5159 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005160 else if (!strcmp(args[1], "tcp-check")) {
5161 /* use raw TCPCHK send/expect to check servers' health */
5162 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5163 err_code |= ERR_WARN;
5164
5165 free(curproxy->check_req);
5166 curproxy->check_req = NULL;
5167 curproxy->options2 &= ~PR_O2_CHK_ANY;
5168 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005169 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5170 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005171 }
Simon Horman98637e52014-06-20 12:30:16 +09005172 else if (!strcmp(args[1], "external-check")) {
5173 /* excute an external command to check servers' health */
5174 free(curproxy->check_req);
5175 curproxy->check_req = NULL;
5176 curproxy->options2 &= ~PR_O2_CHK_ANY;
5177 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005178 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5179 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005180 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005181 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005182 int cur_arg;
5183
5184 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5185 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005186 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005187
Willy Tarreau87cf5142011-08-19 22:57:24 +02005188 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005189
5190 free(curproxy->fwdfor_hdr_name);
5191 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5192 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5193
5194 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5195 cur_arg = 2;
5196 while (*(args[cur_arg])) {
5197 if (!strcmp(args[cur_arg], "except")) {
5198 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005199 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005200 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5201 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005204 }
5205 /* flush useless bits */
5206 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005207 cur_arg += 2;
5208 } else if (!strcmp(args[cur_arg], "header")) {
5209 /* suboption header - needs additional argument for it */
5210 if (*(args[cur_arg+1]) == 0) {
5211 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5212 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005215 }
5216 free(curproxy->fwdfor_hdr_name);
5217 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5218 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5219 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005220 } else if (!strcmp(args[cur_arg], "if-none")) {
5221 curproxy->options &= ~PR_O_FF_ALWAYS;
5222 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005223 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005224 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005225 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005226 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005229 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005230 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005231 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005232 else if (!strcmp(args[1], "originalto")) {
5233 int cur_arg;
5234
5235 /* insert x-original-to field, but not for the IP address listed as an except.
5236 * set default options (ie: bitfield, header name, etc)
5237 */
5238
5239 curproxy->options |= PR_O_ORGTO;
5240
5241 free(curproxy->orgto_hdr_name);
5242 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5243 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5244
Willy Tarreau87cf5142011-08-19 22:57:24 +02005245 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005246 cur_arg = 2;
5247 while (*(args[cur_arg])) {
5248 if (!strcmp(args[cur_arg], "except")) {
5249 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005250 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 +02005251 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5252 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005253 err_code |= ERR_ALERT | ERR_FATAL;
5254 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005255 }
5256 /* flush useless bits */
5257 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5258 cur_arg += 2;
5259 } else if (!strcmp(args[cur_arg], "header")) {
5260 /* suboption header - needs additional argument for it */
5261 if (*(args[cur_arg+1]) == 0) {
5262 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5263 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005266 }
5267 free(curproxy->orgto_hdr_name);
5268 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5269 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5270 cur_arg += 2;
5271 } else {
5272 /* unknown suboption - catchall */
5273 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5274 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005277 }
5278 } /* end while loop */
5279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 else {
5281 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 }
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005287 else if (!strcmp(args[0], "default_backend")) {
5288 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005290
5291 if (*(args[1]) == 0) {
5292 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005295 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005296 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005297 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005298
5299 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5300 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005303 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005304 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005305
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005306 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5307 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 +01005308 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005309 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 /* enable reconnections to dispatch */
5311 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005312
5313 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005316 else if (!strcmp(args[0], "http-reuse")) {
5317 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5318 err_code |= ERR_WARN;
5319
5320 if (strcmp(args[1], "never") == 0) {
5321 /* enable a graceful server shutdown on an HTTP 404 response */
5322 curproxy->options &= ~PR_O_REUSE_MASK;
5323 curproxy->options |= PR_O_REUSE_NEVR;
5324 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5325 goto out;
5326 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005327 else if (strcmp(args[1], "safe") == 0) {
5328 /* enable a graceful server shutdown on an HTTP 404 response */
5329 curproxy->options &= ~PR_O_REUSE_MASK;
5330 curproxy->options |= PR_O_REUSE_SAFE;
5331 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5332 goto out;
5333 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005334 else if (strcmp(args[1], "aggressive") == 0) {
5335 curproxy->options &= ~PR_O_REUSE_MASK;
5336 curproxy->options |= PR_O_REUSE_AGGR;
5337 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5338 goto out;
5339 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005340 else if (strcmp(args[1], "always") == 0) {
5341 /* enable a graceful server shutdown on an HTTP 404 response */
5342 curproxy->options &= ~PR_O_REUSE_MASK;
5343 curproxy->options |= PR_O_REUSE_ALWS;
5344 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5345 goto out;
5346 }
5347 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005348 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
5352 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005353 else if (!strcmp(args[0], "http-check")) {
5354 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005355 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005356
5357 if (strcmp(args[1], "disable-on-404") == 0) {
5358 /* enable a graceful server shutdown on an HTTP 404 response */
5359 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005360 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5361 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005362 }
Willy Tarreauef781042010-01-27 11:53:01 +01005363 else if (strcmp(args[1], "send-state") == 0) {
5364 /* enable emission of the apparent state of a server in HTTP checks */
5365 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005366 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5367 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005368 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005369 else if (strcmp(args[1], "expect") == 0) {
5370 const char *ptr_arg;
5371 int cur_arg;
5372
5373 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5374 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
5377 }
5378
5379 cur_arg = 2;
5380 /* consider exclamation marks, sole or at the beginning of a word */
5381 while (*(ptr_arg = args[cur_arg])) {
5382 while (*ptr_arg == '!') {
5383 curproxy->options2 ^= PR_O2_EXP_INV;
5384 ptr_arg++;
5385 }
5386 if (*ptr_arg)
5387 break;
5388 cur_arg++;
5389 }
5390 /* now ptr_arg points to the beginning of a word past any possible
5391 * exclamation mark, and cur_arg is the argument which holds this word.
5392 */
5393 if (strcmp(ptr_arg, "status") == 0) {
5394 if (!*(args[cur_arg + 1])) {
5395 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5396 file, linenum, args[0], args[1], ptr_arg);
5397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
5399 }
5400 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005401 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005402 curproxy->expect_str = strdup(args[cur_arg + 1]);
5403 }
5404 else if (strcmp(ptr_arg, "string") == 0) {
5405 if (!*(args[cur_arg + 1])) {
5406 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5407 file, linenum, args[0], args[1], ptr_arg);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005412 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005413 curproxy->expect_str = strdup(args[cur_arg + 1]);
5414 }
5415 else if (strcmp(ptr_arg, "rstatus") == 0) {
5416 if (!*(args[cur_arg + 1])) {
5417 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5418 file, linenum, args[0], args[1], ptr_arg);
5419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
5421 }
5422 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005423 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005424 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005425 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005426 free(curproxy->expect_regex);
5427 curproxy->expect_regex = NULL;
5428 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005429 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005430 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5431 error = NULL;
5432 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5433 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5434 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5435 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
5438 }
5439 }
5440 else if (strcmp(ptr_arg, "rstring") == 0) {
5441 if (!*(args[cur_arg + 1])) {
5442 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5443 file, linenum, args[0], args[1], ptr_arg);
5444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
5447 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005448 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005449 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005450 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005451 free(curproxy->expect_regex);
5452 curproxy->expect_regex = NULL;
5453 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005454 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005455 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5456 error = NULL;
5457 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5458 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5459 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5460 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
5463 }
5464 }
5465 else {
5466 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5467 file, linenum, args[0], args[1], ptr_arg);
5468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
5470 }
5471 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005472 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005473 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 +02005474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005476 }
5477 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005478 else if (!strcmp(args[0], "tcp-check")) {
5479 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5480 err_code |= ERR_WARN;
5481
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005482 if (strcmp(args[1], "comment") == 0) {
5483 int cur_arg;
5484 struct tcpcheck_rule *tcpcheck;
5485
5486 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005487 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005488 tcpcheck->action = TCPCHK_ACT_COMMENT;
5489
5490 if (!*args[cur_arg + 1]) {
5491 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5492 file, linenum, args[cur_arg]);
5493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
5495 }
5496
5497 tcpcheck->comment = strdup(args[cur_arg + 1]);
5498
5499 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005500 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5501 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005502 }
5503 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005504 const char *ptr_arg;
5505 int cur_arg;
5506 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005507
5508 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005509 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5510 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5511 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5512 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5513 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005514
Willy Tarreau5581c272015-05-13 12:24:53 +02005515 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5516 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5517 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5518 file, linenum);
5519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005521 }
5522
5523 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005524 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005525 tcpcheck->action = TCPCHK_ACT_CONNECT;
5526
5527 /* parsing each parameters to fill up the rule */
5528 while (*(ptr_arg = args[cur_arg])) {
5529 /* tcp port */
5530 if (strcmp(args[cur_arg], "port") == 0) {
5531 if ( (atol(args[cur_arg + 1]) > 65535) ||
5532 (atol(args[cur_arg + 1]) < 1) ){
5533 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5534 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
5537 }
5538 tcpcheck->port = atol(args[cur_arg + 1]);
5539 cur_arg += 2;
5540 }
5541 /* send proxy protocol */
5542 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5543 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5544 cur_arg++;
5545 }
5546#ifdef USE_OPENSSL
5547 else if (strcmp(args[cur_arg], "ssl") == 0) {
5548 curproxy->options |= PR_O_TCPCHK_SSL;
5549 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5550 cur_arg++;
5551 }
5552#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005553 /* comment for this tcpcheck line */
5554 else if (strcmp(args[cur_arg], "comment") == 0) {
5555 if (!*args[cur_arg + 1]) {
5556 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5557 file, linenum, args[cur_arg]);
5558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
5560 }
5561 tcpcheck->comment = strdup(args[cur_arg + 1]);
5562 cur_arg += 2;
5563 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005564 else {
5565#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005566 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 +01005567#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005568 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 +01005569#endif /* USE_OPENSSL */
5570 file, linenum, args[0], args[1], args[cur_arg]);
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
5573 }
5574
5575 }
5576
5577 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5578 }
5579 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580 if (! *(args[2]) ) {
5581 /* SEND string expected */
5582 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5583 file, linenum, args[0], args[1], args[2]);
5584 err_code |= ERR_ALERT | ERR_FATAL;
5585 goto out;
5586 } else {
5587 struct tcpcheck_rule *tcpcheck;
5588
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005589 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005590
5591 tcpcheck->action = TCPCHK_ACT_SEND;
5592 tcpcheck->string_len = strlen(args[2]);
5593 tcpcheck->string = strdup(args[2]);
5594 tcpcheck->expect_regex = NULL;
5595
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005596 /* comment for this tcpcheck line */
5597 if (strcmp(args[3], "comment") == 0) {
5598 if (!*args[4]) {
5599 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5600 file, linenum, args[3]);
5601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
5603 }
5604 tcpcheck->comment = strdup(args[4]);
5605 }
5606
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005607 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5608 }
5609 }
5610 else if (strcmp(args[1], "send-binary") == 0) {
5611 if (! *(args[2]) ) {
5612 /* SEND binary string expected */
5613 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5614 file, linenum, args[0], args[1], args[2]);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 } else {
5618 struct tcpcheck_rule *tcpcheck;
5619 char *err = NULL;
5620
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005621 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005622
5623 tcpcheck->action = TCPCHK_ACT_SEND;
5624 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5625 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5626 file, linenum, args[0], args[1], args[2], err);
5627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
5629 }
5630 tcpcheck->expect_regex = NULL;
5631
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005632 /* comment for this tcpcheck line */
5633 if (strcmp(args[3], "comment") == 0) {
5634 if (!*args[4]) {
5635 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5636 file, linenum, args[3]);
5637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
5639 }
5640 tcpcheck->comment = strdup(args[4]);
5641 }
5642
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005643 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5644 }
5645 }
5646 else if (strcmp(args[1], "expect") == 0) {
5647 const char *ptr_arg;
5648 int cur_arg;
5649 int inverse = 0;
5650
5651 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5652 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
5655 }
5656
5657 cur_arg = 2;
5658 /* consider exclamation marks, sole or at the beginning of a word */
5659 while (*(ptr_arg = args[cur_arg])) {
5660 while (*ptr_arg == '!') {
5661 inverse = !inverse;
5662 ptr_arg++;
5663 }
5664 if (*ptr_arg)
5665 break;
5666 cur_arg++;
5667 }
5668 /* now ptr_arg points to the beginning of a word past any possible
5669 * exclamation mark, and cur_arg is the argument which holds this word.
5670 */
5671 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005672 struct tcpcheck_rule *tcpcheck;
5673 char *err = NULL;
5674
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005675 if (!*(args[cur_arg + 1])) {
5676 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5677 file, linenum, args[0], args[1], ptr_arg);
5678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
5680 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005681
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005682 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005683
5684 tcpcheck->action = TCPCHK_ACT_EXPECT;
5685 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5686 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5687 file, linenum, args[0], args[1], args[2], err);
5688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
5691 tcpcheck->expect_regex = NULL;
5692 tcpcheck->inverse = inverse;
5693
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005694 /* tcpcheck comment */
5695 cur_arg += 2;
5696 if (strcmp(args[cur_arg], "comment") == 0) {
5697 if (!*args[cur_arg + 1]) {
5698 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5699 file, linenum, args[cur_arg + 1]);
5700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
5702 }
5703 tcpcheck->comment = strdup(args[cur_arg + 1]);
5704 }
5705
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005706 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5707 }
5708 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005709 struct tcpcheck_rule *tcpcheck;
5710
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005711 if (!*(args[cur_arg + 1])) {
5712 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5713 file, linenum, args[0], args[1], ptr_arg);
5714 err_code |= ERR_ALERT | ERR_FATAL;
5715 goto out;
5716 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005717
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005718 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005719
5720 tcpcheck->action = TCPCHK_ACT_EXPECT;
5721 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5722 tcpcheck->string = strdup(args[cur_arg + 1]);
5723 tcpcheck->expect_regex = NULL;
5724 tcpcheck->inverse = inverse;
5725
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005726 /* tcpcheck comment */
5727 cur_arg += 2;
5728 if (strcmp(args[cur_arg], "comment") == 0) {
5729 if (!*args[cur_arg + 1]) {
5730 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5731 file, linenum, args[cur_arg + 1]);
5732 err_code |= ERR_ALERT | ERR_FATAL;
5733 goto out;
5734 }
5735 tcpcheck->comment = strdup(args[cur_arg + 1]);
5736 }
5737
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005738 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5739 }
5740 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005741 struct tcpcheck_rule *tcpcheck;
5742
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005743 if (!*(args[cur_arg + 1])) {
5744 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5745 file, linenum, args[0], args[1], ptr_arg);
5746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
5748 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005749
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005750 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005751
5752 tcpcheck->action = TCPCHK_ACT_EXPECT;
5753 tcpcheck->string_len = 0;
5754 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005755 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5756 error = NULL;
5757 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5758 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5759 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5760 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
5763 }
5764 tcpcheck->inverse = inverse;
5765
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005766 /* tcpcheck comment */
5767 cur_arg += 2;
5768 if (strcmp(args[cur_arg], "comment") == 0) {
5769 if (!*args[cur_arg + 1]) {
5770 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5771 file, linenum, args[cur_arg + 1]);
5772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
5774 }
5775 tcpcheck->comment = strdup(args[cur_arg + 1]);
5776 }
5777
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005778 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5779 }
5780 else {
5781 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5782 file, linenum, args[0], args[1], ptr_arg);
5783 err_code |= ERR_ALERT | ERR_FATAL;
5784 goto out;
5785 }
5786 }
5787 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005788 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
5791 }
5792 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005793 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005794 if (curproxy == &defproxy) {
5795 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005798 }
5799
Willy Tarreaub80c2302007-11-30 20:51:32 +01005800 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005801 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005802
5803 if (strcmp(args[1], "fail") == 0) {
5804 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005805 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005806 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5807 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005808 err_code |= ERR_ALERT | ERR_FATAL;
5809 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005810 }
5811
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005812 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5813 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5814 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005817 }
5818 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5819 }
5820 else {
5821 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005822 err_code |= ERR_ALERT | ERR_FATAL;
5823 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005824 }
5825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826#ifdef TPROXY
5827 else if (!strcmp(args[0], "transparent")) {
5828 /* enable transparent proxy connections */
5829 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005830 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
5833#endif
5834 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005835 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005836 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005837
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 if (*(args[1]) == 0) {
5839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005840 err_code |= ERR_ALERT | ERR_FATAL;
5841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 }
5843 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005844 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005847 else if (!strcmp(args[0], "backlog")) { /* backlog */
5848 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005849 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005850
5851 if (*(args[1]) == 0) {
5852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005853 err_code |= ERR_ALERT | ERR_FATAL;
5854 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005855 }
5856 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005857 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5858 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005859 }
Willy Tarreau86034312006-12-29 00:10:33 +01005860 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005861 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005862 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005863
Willy Tarreau86034312006-12-29 00:10:33 +01005864 if (*(args[1]) == 0) {
5865 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005868 }
5869 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005870 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5871 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5874 if (*(args[1]) == 0) {
5875 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005879 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5880 if (err) {
5881 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5882 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005885 }
5886 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005887 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 }
5890 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005891 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005892 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005893 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005894
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895 if (curproxy == &defproxy) {
5896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005900 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005901 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005902
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005903 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005904 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005905 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005906 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005907 goto out;
5908 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005909
5910 proto = protocol_by_family(sk->ss_family);
5911 if (!proto || !proto->connect) {
5912 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5913 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
5916 }
5917
5918 if (port1 != port2) {
5919 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5920 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005921 err_code |= ERR_ALERT | ERR_FATAL;
5922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005924
5925 if (!port1) {
5926 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5927 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
5930 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005931
William Lallemanddf1425a2015-04-28 20:17:49 +02005932 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5933 goto out;
5934
Willy Tarreaud5191e72010-02-09 20:50:45 +01005935 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005936 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 }
5938 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005940 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005941
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005942 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5943 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005944 err_code |= ERR_ALERT | ERR_FATAL;
5945 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005948 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005949 /**
5950 * The syntax for hash-type config element is
5951 * hash-type {map-based|consistent} [[<algo>] avalanche]
5952 *
5953 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5954 */
5955 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005956
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005957 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5958 err_code |= ERR_WARN;
5959
5960 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005961 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5962 }
5963 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005964 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5965 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005966 else if (strcmp(args[1], "avalanche") == 0) {
5967 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]);
5968 err_code |= ERR_ALERT | ERR_FATAL;
5969 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005970 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005971 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005972 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005973 err_code |= ERR_ALERT | ERR_FATAL;
5974 goto out;
5975 }
Bhaskar98634f02013-10-29 23:30:51 -04005976
5977 /* set the hash function to use */
5978 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005979 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005980 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005981
5982 /* if consistent with no argument, then avalanche modifier is also applied */
5983 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5984 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005985 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005986 /* set the hash function */
5987 if (!strcmp(args[2], "sdbm")) {
5988 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5989 }
5990 else if (!strcmp(args[2], "djb2")) {
5991 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005992 }
5993 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005994 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005995 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005996 else if (!strcmp(args[2], "crc32")) {
5997 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5998 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005999 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01006000 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 -05006001 err_code |= ERR_ALERT | ERR_FATAL;
6002 goto out;
6003 }
6004
6005 /* set the hash modifier */
6006 if (!strcmp(args[3], "avalanche")) {
6007 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
6008 }
6009 else if (*args[3]) {
6010 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
6011 err_code |= ERR_ALERT | ERR_FATAL;
6012 goto out;
6013 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01006014 }
William Lallemanda73203e2012-03-12 12:48:57 +01006015 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04006016 else if (strcmp(args[0], "hash-balance-factor") == 0) {
6017 if (*(args[1]) == 0) {
6018 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
6019 err_code |= ERR_ALERT | ERR_FATAL;
6020 goto out;
6021 }
6022 curproxy->lbprm.chash.balance_factor = atol(args[1]);
6023 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
6024 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
6025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
6027 }
6028 }
William Lallemanda73203e2012-03-12 12:48:57 +01006029 else if (strcmp(args[0], "unique-id-format") == 0) {
6030 if (!*(args[1])) {
6031 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6032 err_code |= ERR_ALERT | ERR_FATAL;
6033 goto out;
6034 }
William Lallemand3203ff42012-11-11 17:30:56 +01006035 if (*(args[2])) {
6036 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6037 err_code |= ERR_ALERT | ERR_FATAL;
6038 goto out;
6039 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006040 free(curproxy->conf.uniqueid_format_string);
6041 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006042
Willy Tarreau62a61232013-04-12 18:13:46 +02006043 free(curproxy->conf.uif_file);
6044 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6045 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006046 }
William Lallemanda73203e2012-03-12 12:48:57 +01006047
6048 else if (strcmp(args[0], "unique-id-header") == 0) {
6049 if (!*(args[1])) {
6050 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6051 err_code |= ERR_ALERT | ERR_FATAL;
6052 goto out;
6053 }
6054 free(curproxy->header_unique_id);
6055 curproxy->header_unique_id = strdup(args[1]);
6056 }
6057
William Lallemand723b73a2012-02-08 16:37:49 +01006058 else if (strcmp(args[0], "log-format") == 0) {
6059 if (!*(args[1])) {
6060 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6061 err_code |= ERR_ALERT | ERR_FATAL;
6062 goto out;
6063 }
William Lallemand3203ff42012-11-11 17:30:56 +01006064 if (*(args[2])) {
6065 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6066 err_code |= ERR_ALERT | ERR_FATAL;
6067 goto out;
6068 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006069
Willy Tarreau62a61232013-04-12 18:13:46 +02006070 if (curproxy->conf.logformat_string != default_http_log_format &&
6071 curproxy->conf.logformat_string != default_tcp_log_format &&
6072 curproxy->conf.logformat_string != clf_http_log_format)
6073 free(curproxy->conf.logformat_string);
6074 curproxy->conf.logformat_string = strdup(args[1]);
6075
6076 free(curproxy->conf.lfs_file);
6077 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6078 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006079
6080 /* get a chance to improve log-format error reporting by
6081 * reporting the correct line-number when possible.
6082 */
6083 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6084 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6085 file, linenum, curproxy->id);
6086 err_code |= ERR_WARN;
6087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006088 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006089 else if (!strcmp(args[0], "log-format-sd")) {
6090 if (!*(args[1])) {
6091 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6092 err_code |= ERR_ALERT | ERR_FATAL;
6093 goto out;
6094 }
6095 if (*(args[2])) {
6096 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6097 err_code |= ERR_ALERT | ERR_FATAL;
6098 goto out;
6099 }
6100
6101 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6102 free(curproxy->conf.logformat_sd_string);
6103 curproxy->conf.logformat_sd_string = strdup(args[1]);
6104
6105 free(curproxy->conf.lfsd_file);
6106 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6107 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6108
6109 /* get a chance to improve log-format-sd error reporting by
6110 * reporting the correct line-number when possible.
6111 */
6112 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6113 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6114 file, linenum, curproxy->id);
6115 err_code |= ERR_WARN;
6116 }
6117 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006118 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6119 if (*(args[1]) == 0) {
6120 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6121 err_code |= ERR_ALERT | ERR_FATAL;
6122 goto out;
6123 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006124 chunk_destroy(&curproxy->log_tag);
6125 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006126 }
William Lallemand0f99e342011-10-12 17:50:54 +02006127 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6128 /* delete previous herited or defined syslog servers */
6129 struct logsrv *back;
6130
6131 if (*(args[1]) != 0) {
6132 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6133 err_code |= ERR_ALERT | ERR_FATAL;
6134 goto out;
6135 }
6136
William Lallemand723b73a2012-02-08 16:37:49 +01006137 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6138 LIST_DEL(&tmplogsrv->list);
6139 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006140 }
6141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006143 struct logsrv *logsrv;
6144
Willy Tarreaubaaee002006-06-26 02:48:02 +02006145 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006146 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006147 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006148 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006149 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006150 LIST_INIT(&node->list);
6151 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 }
6154 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006155 struct sockaddr_storage *sk;
6156 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006157 int arg = 0;
6158 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006159
Vincent Bernat02779b62016-04-03 13:48:43 +02006160 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161
Willy Tarreau18324f52014-06-27 18:10:07 +02006162 /* just after the address, a length may be specified */
6163 if (strcmp(args[arg+2], "len") == 0) {
6164 len = atoi(args[arg+3]);
6165 if (len < 80 || len > 65535) {
6166 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6167 file, linenum, args[arg+3]);
6168 err_code |= ERR_ALERT | ERR_FATAL;
6169 goto out;
6170 }
6171 logsrv->maxlen = len;
6172
6173 /* skip these two args */
6174 arg += 2;
6175 }
6176 else
6177 logsrv->maxlen = MAX_SYSLOG_LEN;
6178
6179 if (logsrv->maxlen > global.max_syslog_len) {
6180 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006181 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6182 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6183 logline = my_realloc2(logline, global.max_syslog_len + 1);
6184 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006185 }
6186
Dragan Dosen1322d092015-09-22 16:05:32 +02006187 /* after the length, a format may be specified */
6188 if (strcmp(args[arg+2], "format") == 0) {
6189 logsrv->format = get_log_format(args[arg+3]);
6190 if (logsrv->format < 0) {
6191 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6192 err_code |= ERR_ALERT | ERR_FATAL;
6193 goto out;
6194 }
6195
6196 /* skip these two args */
6197 arg += 2;
6198 }
6199
William Lallemanddf1425a2015-04-28 20:17:49 +02006200 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6201 goto out;
6202
Willy Tarreau18324f52014-06-27 18:10:07 +02006203 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006204 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006205 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006206 err_code |= ERR_ALERT | ERR_FATAL;
6207 goto out;
6208
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 }
6210
William Lallemand0f99e342011-10-12 17:50:54 +02006211 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006212 if (*(args[arg+3])) {
6213 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006214 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006215 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006216 err_code |= ERR_ALERT | ERR_FATAL;
6217 goto out;
6218
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 }
6220 }
6221
William Lallemand0f99e342011-10-12 17:50:54 +02006222 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006223 if (*(args[arg+4])) {
6224 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006225 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006226 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006227 err_code |= ERR_ALERT | ERR_FATAL;
6228 goto out;
6229
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006230 }
6231 }
6232
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006233 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006234 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006235 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006236 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006237 goto out;
6238 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006239
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006240 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006241
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006242 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006243 if (port1 != port2) {
6244 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6245 file, linenum, args[0], args[1]);
6246 err_code |= ERR_ALERT | ERR_FATAL;
6247 goto out;
6248 }
6249
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006250 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006251 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006252 }
William Lallemand0f99e342011-10-12 17:50:54 +02006253
6254 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006255 }
6256 else {
6257 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006259 err_code |= ERR_ALERT | ERR_FATAL;
6260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 }
6262 }
6263 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006264 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006265 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006266 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006267 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006268
Willy Tarreau977b8e42006-12-29 14:19:17 +01006269 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006270 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006271
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006273 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6274 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006275 err_code |= ERR_ALERT | ERR_FATAL;
6276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006278
6279 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006280 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6281 free(curproxy->conn_src.iface_name);
6282 curproxy->conn_src.iface_name = NULL;
6283 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006284
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006285 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006286 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006287 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006288 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006289 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006290 goto out;
6291 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006292
6293 proto = protocol_by_family(sk->ss_family);
6294 if (!proto || !proto->connect) {
6295 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006296 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006297 err_code |= ERR_ALERT | ERR_FATAL;
6298 goto out;
6299 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006300
6301 if (port1 != port2) {
6302 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6303 file, linenum, args[0], args[1]);
6304 err_code |= ERR_ALERT | ERR_FATAL;
6305 goto out;
6306 }
6307
Willy Tarreauef9a3602012-12-08 22:29:20 +01006308 curproxy->conn_src.source_addr = *sk;
6309 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006310
6311 cur_arg = 2;
6312 while (*(args[cur_arg])) {
6313 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006314#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006315 if (!*args[cur_arg + 1]) {
6316 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6317 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006318 err_code |= ERR_ALERT | ERR_FATAL;
6319 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006320 }
6321
6322 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006323 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6324 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006325 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006326 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6327 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006328 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6329 char *name, *end;
6330
6331 name = args[cur_arg+1] + 7;
6332 while (isspace(*name))
6333 name++;
6334
6335 end = name;
6336 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6337 end++;
6338
Willy Tarreauef9a3602012-12-08 22:29:20 +01006339 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6340 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6341 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6342 curproxy->conn_src.bind_hdr_len = end - name;
6343 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6344 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6345 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006346
6347 /* now look for an occurrence number */
6348 while (isspace(*end))
6349 end++;
6350 if (*end == ',') {
6351 end++;
6352 name = end;
6353 if (*end == '-')
6354 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006355 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006356 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006357 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006358 }
6359
Willy Tarreauef9a3602012-12-08 22:29:20 +01006360 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006361 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6362 " occurrences values smaller than %d.\n",
6363 file, linenum, MAX_HDR_HISTORY);
6364 err_code |= ERR_ALERT | ERR_FATAL;
6365 goto out;
6366 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006367 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006368 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006369
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006370 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006371 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006372 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006373 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006375 goto out;
6376 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006377
6378 proto = protocol_by_family(sk->ss_family);
6379 if (!proto || !proto->connect) {
6380 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6381 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006382 err_code |= ERR_ALERT | ERR_FATAL;
6383 goto out;
6384 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006385
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006386 if (port1 != port2) {
6387 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6388 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006389 err_code |= ERR_ALERT | ERR_FATAL;
6390 goto out;
6391 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006392 curproxy->conn_src.tproxy_addr = *sk;
6393 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006394 }
6395 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006396#else /* no TPROXY support */
6397 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006398 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006399 err_code |= ERR_ALERT | ERR_FATAL;
6400 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006401#endif
6402 cur_arg += 2;
6403 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006404 }
6405
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006406 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6407#ifdef SO_BINDTODEVICE
6408 if (!*args[cur_arg + 1]) {
6409 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6410 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006411 err_code |= ERR_ALERT | ERR_FATAL;
6412 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006413 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006414 free(curproxy->conn_src.iface_name);
6415 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6416 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006417 global.last_checks |= LSTCHK_NETADM;
6418#else
6419 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6420 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006421 err_code |= ERR_ALERT | ERR_FATAL;
6422 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006423#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006424 cur_arg += 2;
6425 continue;
6426 }
6427 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006428 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006429 err_code |= ERR_ALERT | ERR_FATAL;
6430 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006432 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006433 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6434 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6435 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006436 err_code |= ERR_ALERT | ERR_FATAL;
6437 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006438 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006440 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6442 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006443 err_code |= ERR_ALERT | ERR_FATAL;
6444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006446
6447 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006448 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006449 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452 }
6453 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006454 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006455 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006456 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459 }
6460 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006461 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006462 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006463 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006466 }
6467 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006468 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006469 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006470 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 }
6474 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006476 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006477 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006481 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006482 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006483 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006484 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006486 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006492 err_code |= ERR_ALERT | ERR_FATAL;
6493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006495
6496 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006497 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006498 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006499 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 }
6502 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006504 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006505 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 }
6509 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006511 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006512 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006515 }
6516 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006517 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006518 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006519 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006520 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522 }
6523 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006524 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006525 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006526 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006527 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006530 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006531 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006532 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006533 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006534 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006535 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006538 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006539
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 if (curproxy == &defproxy) {
6541 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006542 err_code |= ERR_ALERT | ERR_FATAL;
6543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006545 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006546 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548 if (*(args[1]) == 0) {
6549 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006550 err_code |= ERR_ALERT | ERR_FATAL;
6551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006553
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006554 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006555 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6556 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6557 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006558 err_code |= ERR_ALERT | ERR_FATAL;
6559 goto out;
6560 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006561 err_code |= warnif_cond_conflicts(cond,
6562 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6563 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006564 }
6565 else if (*args[2]) {
6566 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6567 file, linenum, args[0], args[2]);
6568 err_code |= ERR_ALERT | ERR_FATAL;
6569 goto out;
6570 }
6571
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006572 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006573 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006574 wl->s = strdup(args[1]);
6575 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006576 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 }
6578 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006579 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6581 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006582 err_code |= ERR_ALERT | ERR_FATAL;
6583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006585
Willy Tarreauade5ec42010-01-28 19:33:49 +01006586 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006587 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006588 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006589 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591 }
6592 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006593 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006594 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006595 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006596 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006598 }
6599 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006600 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006601 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006602 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006603 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 }
6606 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006607 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006608 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006610 err_code |= ERR_ALERT | ERR_FATAL;
6611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006612 }
6613
Willy Tarreauade5ec42010-01-28 19:33:49 +01006614 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006615 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006616 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006617 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006619 }
6620 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006621 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006622 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006623 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006624 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006626 }
6627 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006628 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006629 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006630 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006631 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006633 }
6634 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006635 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006636
Willy Tarreaubaaee002006-06-26 02:48:02 +02006637 if (curproxy == &defproxy) {
6638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006639 err_code |= ERR_ALERT | ERR_FATAL;
6640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006641 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006642 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006643 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006644
Willy Tarreaubaaee002006-06-26 02:48:02 +02006645 if (*(args[1]) == 0) {
6646 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006647 err_code |= ERR_ALERT | ERR_FATAL;
6648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006649 }
6650
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006651 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006652 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6653 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6654 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006655 err_code |= ERR_ALERT | ERR_FATAL;
6656 goto out;
6657 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006658 err_code |= warnif_cond_conflicts(cond,
6659 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6660 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006661 }
6662 else if (*args[2]) {
6663 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6664 file, linenum, args[0], args[2]);
6665 err_code |= ERR_ALERT | ERR_FATAL;
6666 goto out;
6667 }
6668
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006669 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006670 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006671 wl->s = strdup(args[1]);
6672 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006673 }
6674 else if (!strcmp(args[0], "errorloc") ||
6675 !strcmp(args[0], "errorloc302") ||
6676 !strcmp(args[0], "errorloc303")) { /* error location */
6677 int errnum, errlen;
6678 char *err;
6679
Willy Tarreau977b8e42006-12-29 14:19:17 +01006680 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006681 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006682
Willy Tarreaubaaee002006-06-26 02:48:02 +02006683 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006684 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006685 err_code |= ERR_ALERT | ERR_FATAL;
6686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006687 }
6688
6689 errnum = atol(args[1]);
6690 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006691 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6692 err = malloc(errlen);
6693 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006694 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006695 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6696 err = malloc(errlen);
6697 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006698 }
6699
Willy Tarreau0f772532006-12-23 20:51:41 +01006700 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6701 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006702 chunk_destroy(&curproxy->errmsg[rc]);
6703 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006704 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006706 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006707
6708 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006709 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6710 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006711 free(err);
6712 }
6713 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006714 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6715 int errnum, errlen, fd;
6716 char *err;
6717 struct stat stat;
6718
6719 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006720 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006721
6722 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006723 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006724 err_code |= ERR_ALERT | ERR_FATAL;
6725 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006726 }
6727
6728 fd = open(args[2], O_RDONLY);
6729 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6730 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6731 file, linenum, args[2], args[1]);
6732 if (fd >= 0)
6733 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006734 err_code |= ERR_ALERT | ERR_FATAL;
6735 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006736 }
6737
Willy Tarreau27a674e2009-08-17 07:23:33 +02006738 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006739 errlen = stat.st_size;
6740 } else {
6741 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006742 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006743 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006744 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006745 }
6746
6747 err = malloc(errlen); /* malloc() must succeed during parsing */
6748 errnum = read(fd, err, errlen);
6749 if (errnum != errlen) {
6750 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6751 file, linenum, args[2], args[1]);
6752 close(fd);
6753 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006754 err_code |= ERR_ALERT | ERR_FATAL;
6755 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006756 }
6757 close(fd);
6758
6759 errnum = atol(args[1]);
6760 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6761 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006762 chunk_destroy(&curproxy->errmsg[rc]);
6763 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006764 break;
6765 }
6766 }
6767
6768 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006769 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6770 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006771 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006772 free(err);
6773 }
6774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006775 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006776 struct cfg_kw_list *kwl;
6777 int index;
6778
6779 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6780 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6781 if (kwl->kw[index].section != CFG_LISTEN)
6782 continue;
6783 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6784 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006785 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006786 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006787 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006788 err_code |= ERR_ALERT | ERR_FATAL;
6789 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006790 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006791 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006792 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006793 err_code |= ERR_WARN;
6794 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006795 }
Willy Tarreau93893792009-07-23 13:19:11 +02006796 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006797 }
6798 }
6799 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006800
Willy Tarreau6daf3432008-01-22 16:44:08 +01006801 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006802 err_code |= ERR_ALERT | ERR_FATAL;
6803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006804 }
Willy Tarreau93893792009-07-23 13:19:11 +02006805 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006806 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006807 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006808}
6809
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006810int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006811cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6812{
6813#ifdef CONFIG_HAP_NS
6814 const char *err;
6815 const char *item = args[0];
6816
6817 if (!strcmp(item, "namespace_list")) {
6818 return 0;
6819 }
6820 else if (!strcmp(item, "namespace")) {
6821 size_t idx = 1;
6822 const char *current;
6823 while (*(current = args[idx++])) {
6824 err = invalid_char(current);
6825 if (err) {
6826 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6827 file, linenum, *err, item, current);
6828 return ERR_ALERT | ERR_FATAL;
6829 }
6830
6831 if (netns_store_lookup(current, strlen(current))) {
6832 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6833 file, linenum, current);
6834 return ERR_ALERT | ERR_FATAL;
6835 }
6836 if (!netns_store_insert(current)) {
6837 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6838 file, linenum, current);
6839 return ERR_ALERT | ERR_FATAL;
6840 }
6841 }
6842 }
6843
6844 return 0;
6845#else
6846 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6847 file, linenum);
6848 return ERR_ALERT | ERR_FATAL;
6849#endif
6850}
6851
6852int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006853cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6854{
6855
6856 int err_code = 0;
6857 const char *err;
6858
6859 if (!strcmp(args[0], "userlist")) { /* new userlist */
6860 struct userlist *newul;
6861
6862 if (!*args[1]) {
6863 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6864 file, linenum, args[0]);
6865 err_code |= ERR_ALERT | ERR_FATAL;
6866 goto out;
6867 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006868 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6869 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006870
6871 err = invalid_char(args[1]);
6872 if (err) {
6873 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6874 file, linenum, *err, args[0], args[1]);
6875 err_code |= ERR_ALERT | ERR_FATAL;
6876 goto out;
6877 }
6878
6879 for (newul = userlist; newul; newul = newul->next)
6880 if (!strcmp(newul->name, args[1])) {
6881 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6882 file, linenum, args[1]);
6883 err_code |= ERR_WARN;
6884 goto out;
6885 }
6886
Vincent Bernat02779b62016-04-03 13:48:43 +02006887 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006888 if (!newul) {
6889 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6890 err_code |= ERR_ALERT | ERR_ABORT;
6891 goto out;
6892 }
6893
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006894 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006895 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006896 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6897 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006898 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006899 goto out;
6900 }
6901
6902 newul->next = userlist;
6903 userlist = newul;
6904
6905 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006906 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006907 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006908 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006909
6910 if (!*args[1]) {
6911 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6912 file, linenum, args[0]);
6913 err_code |= ERR_ALERT | ERR_FATAL;
6914 goto out;
6915 }
6916
6917 err = invalid_char(args[1]);
6918 if (err) {
6919 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6920 file, linenum, *err, args[0], args[1]);
6921 err_code |= ERR_ALERT | ERR_FATAL;
6922 goto out;
6923 }
6924
William Lallemand4ac9f542015-05-28 18:03:51 +02006925 if (!userlist)
6926 goto out;
6927
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006928 for (ag = userlist->groups; ag; ag = ag->next)
6929 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006930 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6931 file, linenum, args[1], userlist->name);
6932 err_code |= ERR_ALERT;
6933 goto out;
6934 }
6935
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006936 ag = calloc(1, sizeof(*ag));
6937 if (!ag) {
6938 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6939 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006940 goto out;
6941 }
6942
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006943 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006944 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006945 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6946 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006947 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006948 goto out;
6949 }
6950
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006951 cur_arg = 2;
6952
6953 while (*args[cur_arg]) {
6954 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006955 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006956 cur_arg += 2;
6957 continue;
6958 } else {
6959 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6960 file, linenum, args[0]);
6961 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006962 free(ag->groupusers);
6963 free(ag->name);
6964 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006965 goto out;
6966 }
6967 }
6968
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006969 ag->next = userlist->groups;
6970 userlist->groups = ag;
6971
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006972 } else if (!strcmp(args[0], "user")) { /* new user */
6973 struct auth_users *newuser;
6974 int cur_arg;
6975
6976 if (!*args[1]) {
6977 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6978 file, linenum, args[0]);
6979 err_code |= ERR_ALERT | ERR_FATAL;
6980 goto out;
6981 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006982 if (!userlist)
6983 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006984
6985 for (newuser = userlist->users; newuser; newuser = newuser->next)
6986 if (!strcmp(newuser->user, args[1])) {
6987 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6988 file, linenum, args[1], userlist->name);
6989 err_code |= ERR_ALERT;
6990 goto out;
6991 }
6992
Vincent Bernat02779b62016-04-03 13:48:43 +02006993 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006994 if (!newuser) {
6995 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6996 err_code |= ERR_ALERT | ERR_ABORT;
6997 goto out;
6998 }
6999
7000 newuser->user = strdup(args[1]);
7001
7002 newuser->next = userlist->users;
7003 userlist->users = newuser;
7004
7005 cur_arg = 2;
7006
7007 while (*args[cur_arg]) {
7008 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02007009#ifdef CONFIG_HAP_CRYPT
7010 if (!crypt("", args[cur_arg + 1])) {
7011 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
7012 file, linenum, newuser->user);
7013 err_code |= ERR_ALERT | ERR_FATAL;
7014 goto out;
7015 }
7016#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007017 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
7018 file, linenum);
7019 err_code |= ERR_ALERT;
7020#endif
7021 newuser->pass = strdup(args[cur_arg + 1]);
7022 cur_arg += 2;
7023 continue;
7024 } else if (!strcmp(args[cur_arg], "insecure-password")) {
7025 newuser->pass = strdup(args[cur_arg + 1]);
7026 newuser->flags |= AU_O_INSECURE;
7027 cur_arg += 2;
7028 continue;
7029 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007030 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007031 cur_arg += 2;
7032 continue;
7033 } else {
7034 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
7035 file, linenum, args[0]);
7036 err_code |= ERR_ALERT | ERR_FATAL;
7037 goto out;
7038 }
7039 }
7040 } else {
7041 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7042 err_code |= ERR_ALERT | ERR_FATAL;
7043 }
7044
7045out:
7046 return err_code;
7047}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048
Christopher Faulet79bdef32016-11-04 22:36:15 +01007049int
7050cfg_parse_scope(const char *file, int linenum, char *line)
7051{
7052 char *beg, *end, *scope = NULL;
7053 int err_code = 0;
7054 const char *err;
7055
7056 beg = line + 1;
7057 end = strchr(beg, ']');
7058
7059 /* Detect end of scope declaration */
7060 if (!end || end == beg) {
7061 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
7062 file, linenum);
7063 err_code |= ERR_ALERT | ERR_FATAL;
7064 goto out;
7065 }
7066
7067 /* Get scope name and check its validity */
7068 scope = my_strndup(beg, end-beg);
7069 err = invalid_char(scope);
7070 if (err) {
7071 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
7072 file, linenum, *err);
7073 err_code |= ERR_ALERT | ERR_ABORT;
7074 goto out;
7075 }
7076
7077 /* Be sure to have a scope declaration alone on its line */
7078 line = end+1;
7079 while (isspace((unsigned char)*line))
7080 line++;
7081 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
7082 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
7083 file, linenum, *line);
7084 err_code |= ERR_ALERT | ERR_ABORT;
7085 goto out;
7086 }
7087
7088 /* We have a valid scope declaration, save it */
7089 free(cfg_scope);
7090 cfg_scope = scope;
7091 scope = NULL;
7092
7093 out:
7094 free(scope);
7095 return err_code;
7096}
7097
Willy Tarreaubaaee002006-06-26 02:48:02 +02007098/*
7099 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007100 * Returns the error code, 0 if OK, or any combination of :
7101 * - ERR_ABORT: must abort ASAP
7102 * - ERR_FATAL: we can continue parsing but not start the service
7103 * - ERR_WARN: a warning has been emitted
7104 * - ERR_ALERT: an alert has been emitted
7105 * Only the two first ones can stop processing, the two others are just
7106 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007107 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007108int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109{
William Lallemand64e84512015-05-12 14:25:37 +02007110 char *thisline;
7111 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007112 FILE *f;
7113 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007114 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007115 struct cfg_section *cs = NULL;
7116 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007117 int readbytes = 0;
7118
7119 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007120 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007121 return -1;
7122 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007123
David Carlier97880bb2016-04-08 10:35:26 +01007124 if ((f=fopen(file,"r")) == NULL) {
7125 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007126 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007128
William Lallemandb2f07452015-05-12 14:27:13 +02007129next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007130 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007131 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007132 char *end;
7133 char *args[MAX_LINE_ARGS + 1];
7134 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007135 int dquote = 0; /* double quote */
7136 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007137
Willy Tarreaubaaee002006-06-26 02:48:02 +02007138 linenum++;
7139
7140 end = line + strlen(line);
7141
William Lallemand64e84512015-05-12 14:25:37 +02007142 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007143 /* Check if we reached the limit and the last char is not \n.
7144 * Watch out for the last line without the terminating '\n'!
7145 */
William Lallemand64e84512015-05-12 14:25:37 +02007146 char *newline;
7147 int newlinesize = linesize * 2;
7148
7149 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7150 if (newline == NULL) {
7151 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7152 file, linenum);
7153 err_code |= ERR_ALERT | ERR_FATAL;
7154 continue;
7155 }
7156
7157 readbytes = linesize - 1;
7158 linesize = newlinesize;
7159 thisline = newline;
7160 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007161 }
7162
William Lallemand64e84512015-05-12 14:25:37 +02007163 readbytes = 0;
7164
Willy Tarreaubaaee002006-06-26 02:48:02 +02007165 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007166 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007167 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007168
Christopher Faulet79bdef32016-11-04 22:36:15 +01007169
7170 if (*line == '[') {/* This is the begining if a scope */
7171 err_code |= cfg_parse_scope(file, linenum, line);
7172 goto next_line;
7173 }
7174
Willy Tarreaubaaee002006-06-26 02:48:02 +02007175 arg = 0;
7176 args[arg] = line;
7177
7178 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007179 if (*line == '"' && !squote) { /* double quote outside single quotes */
7180 if (dquote)
7181 dquote = 0;
7182 else
7183 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007184 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007185 end--;
7186 }
7187 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7188 if (squote)
7189 squote = 0;
7190 else
7191 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007192 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007193 end--;
7194 }
7195 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007196 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7197 * C equivalent value. Other combinations left unchanged (eg: \1).
7198 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007199 int skip = 0;
7200 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7201 *line = line[1];
7202 skip = 1;
7203 }
7204 else if (line[1] == 'r') {
7205 *line = '\r';
7206 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007208 else if (line[1] == 'n') {
7209 *line = '\n';
7210 skip = 1;
7211 }
7212 else if (line[1] == 't') {
7213 *line = '\t';
7214 skip = 1;
7215 }
7216 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007217 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007218 unsigned char hex1, hex2;
7219 hex1 = toupper(line[2]) - '0';
7220 hex2 = toupper(line[3]) - '0';
7221 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7222 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7223 *line = (hex1<<4) + hex2;
7224 skip = 3;
7225 }
7226 else {
7227 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007228 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007229 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007230 } else if (line[1] == '"') {
7231 *line = '"';
7232 skip = 1;
7233 } else if (line[1] == '\'') {
7234 *line = '\'';
7235 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007236 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7237 *line = '$';
7238 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007239 }
7240 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007241 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007242 end -= skip;
7243 }
7244 line++;
7245 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007246 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 /* end of string, end of loop */
7248 *line = 0;
7249 break;
7250 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007251 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007252 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007253 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007254 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007255 line++;
7256 args[++arg] = line;
7257 }
William Lallemandb2f07452015-05-12 14:27:13 +02007258 else if (dquote && *line == '$') {
7259 /* environment variables are evaluated inside double quotes */
7260 char *var_beg;
7261 char *var_end;
7262 char save_char;
7263 char *value;
7264 int val_len;
7265 int newlinesize;
7266 int braces = 0;
7267
7268 var_beg = line + 1;
7269 var_end = var_beg;
7270
7271 if (*var_beg == '{') {
7272 var_beg++;
7273 var_end++;
7274 braces = 1;
7275 }
7276
7277 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7278 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7279 err_code |= ERR_ALERT | ERR_FATAL;
7280 goto next_line; /* skip current line */
7281 }
7282
7283 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7284 var_end++;
7285
7286 save_char = *var_end;
7287 *var_end = '\0';
7288 value = getenv(var_beg);
7289 *var_end = save_char;
7290 val_len = value ? strlen(value) : 0;
7291
7292 if (braces) {
7293 if (*var_end == '}') {
7294 var_end++;
7295 braces = 0;
7296 } else {
7297 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7298 err_code |= ERR_ALERT | ERR_FATAL;
7299 goto next_line; /* skip current line */
7300 }
7301 }
7302
7303 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7304
7305 /* if not enough space in thisline */
7306 if (newlinesize > linesize) {
7307 char *newline;
7308
7309 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7310 if (newline == NULL) {
7311 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7312 err_code |= ERR_ALERT | ERR_FATAL;
7313 goto next_line; /* slip current line */
7314 }
7315 /* recompute pointers if realloc returns a new pointer */
7316 if (newline != thisline) {
7317 int i;
7318 int diff;
7319
7320 for (i = 0; i <= arg; i++) {
7321 diff = args[i] - thisline;
7322 args[i] = newline + diff;
7323 }
7324
7325 diff = var_end - thisline;
7326 var_end = newline + diff;
7327 diff = end - thisline;
7328 end = newline + diff;
7329 diff = line - thisline;
7330 line = newline + diff;
7331 thisline = newline;
7332 }
7333 linesize = newlinesize;
7334 }
7335
7336 /* insert value inside the line */
7337 memmove(line + val_len, var_end, end - var_end + 1);
7338 memcpy(line, value, val_len);
7339 end += val_len - (var_end - line);
7340 line += val_len;
7341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007342 else {
7343 line++;
7344 }
7345 }
William Lallemandb2f07452015-05-12 14:27:13 +02007346
William Lallemandf9873ba2015-05-05 17:37:14 +02007347 if (dquote) {
7348 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7349 err_code |= ERR_ALERT | ERR_FATAL;
7350 }
7351
7352 if (squote) {
7353 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7354 err_code |= ERR_ALERT | ERR_FATAL;
7355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007356
7357 /* empty line */
7358 if (!**args)
7359 continue;
7360
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007361 if (*line) {
7362 /* we had to stop due to too many args.
7363 * Let's terminate the string, print the offending part then cut the
7364 * last arg.
7365 */
7366 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7367 line++;
7368 *line = '\0';
7369
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007370 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007371 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007372 err_code |= ERR_ALERT | ERR_FATAL;
7373 args[arg] = line;
7374 }
7375
Willy Tarreau540abe42007-05-02 20:50:16 +02007376 /* zero out remaining args and ensure that at least one entry
7377 * is zeroed out.
7378 */
7379 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007380 args[arg] = line;
7381 }
7382
Willy Tarreau3842f002009-06-14 11:39:52 +02007383 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007384 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007385 char *tmp;
7386
Willy Tarreau3842f002009-06-14 11:39:52 +02007387 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007388 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007389 for (arg=0; *args[arg+1]; arg++)
7390 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007391 *tmp = '\0'; // fix the next arg to \0
7392 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007393 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007394 else if (!strcmp(args[0], "default")) {
7395 kwm = KWM_DEF;
7396 for (arg=0; *args[arg+1]; arg++)
7397 args[arg] = args[arg+1]; // shift args after inversion
7398 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007399
William Lallemand0f99e342011-10-12 17:50:54 +02007400 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7401 strcmp(args[0], "log") != 0) {
7402 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007403 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007404 }
7405
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007406 /* detect section start */
7407 list_for_each_entry(ics, &sections, list) {
7408 if (strcmp(args[0], ics->section_name) == 0) {
7409 cursection = ics->section_name;
7410 cs = ics;
7411 break;
7412 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007413 }
7414
Willy Tarreaubaaee002006-06-26 02:48:02 +02007415 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007416 if (cs)
7417 err_code |= cs->section_parser(file, linenum, args, kwm);
7418 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007419 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007420 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007421 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007422
7423 if (err_code & ERR_ABORT)
7424 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007425 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007426 free(cfg_scope);
7427 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007428 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007429 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007430 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007431 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007432}
7433
Willy Tarreau64ab6072014-09-16 12:17:36 +02007434/* This function propagates processes from frontend <from> to backend <to> so
7435 * that it is always guaranteed that a backend pointed to by a frontend is
7436 * bound to all of its processes. After that, if the target is a "listen"
7437 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007438 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007439 * checked first to ensure that <to> is already bound to all processes of
7440 * <from>, there is no risk of looping and we ensure to follow the shortest
7441 * path to the destination.
7442 *
7443 * It is possible to set <to> to NULL for the first call so that the function
7444 * takes care of visiting the initial frontend in <from>.
7445 *
7446 * It is important to note that the function relies on the fact that all names
7447 * have already been resolved.
7448 */
7449void propagate_processes(struct proxy *from, struct proxy *to)
7450{
7451 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007452
7453 if (to) {
7454 /* check whether we need to go down */
7455 if (from->bind_proc &&
7456 (from->bind_proc & to->bind_proc) == from->bind_proc)
7457 return;
7458
7459 if (!from->bind_proc && !to->bind_proc)
7460 return;
7461
7462 to->bind_proc = from->bind_proc ?
7463 (to->bind_proc | from->bind_proc) : 0;
7464
7465 /* now propagate down */
7466 from = to;
7467 }
7468
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007469 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007470 return;
7471
Willy Tarreauf6b70012014-12-18 14:00:43 +01007472 if (from->state == PR_STSTOPPED)
7473 return;
7474
Willy Tarreau64ab6072014-09-16 12:17:36 +02007475 /* default_backend */
7476 if (from->defbe.be)
7477 propagate_processes(from, from->defbe.be);
7478
7479 /* use_backend */
7480 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007481 if (rule->dynamic)
7482 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007483 to = rule->be.backend;
7484 propagate_processes(from, to);
7485 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007486}
7487
Willy Tarreaubb925012009-07-23 13:36:36 +02007488/*
7489 * Returns the error code, 0 if OK, or any combination of :
7490 * - ERR_ABORT: must abort ASAP
7491 * - ERR_FATAL: we can continue parsing but not start the service
7492 * - ERR_WARN: a warning has been emitted
7493 * - ERR_ALERT: an alert has been emitted
7494 * Only the two first ones can stop processing, the two others are just
7495 * indicators.
7496 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007497int check_config_validity()
7498{
7499 int cfgerr = 0;
7500 struct proxy *curproxy = NULL;
7501 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007502 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007503 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007504 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007505 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007506
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007507 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007508 /*
7509 * Now, check for the integrity of all that we have collected.
7510 */
7511
7512 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007513 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007514
Willy Tarreau193b8c62012-11-22 00:17:38 +01007515 if (!global.tune.max_http_hdr)
7516 global.tune.max_http_hdr = MAX_HTTP_HDR;
7517
7518 if (!global.tune.cookie_len)
7519 global.tune.cookie_len = CAPTURE_LEN;
7520
7521 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7522
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007523 /* Post initialisation of the users and groups lists. */
7524 err_code = userlist_postinit();
7525 if (err_code != ERR_NONE)
7526 goto out;
7527
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007528 /* first, we will invert the proxy list order */
7529 curproxy = NULL;
7530 while (proxy) {
7531 struct proxy *next;
7532
7533 next = proxy->next;
7534 proxy->next = curproxy;
7535 curproxy = proxy;
7536 if (!next)
7537 break;
7538 proxy = next;
7539 }
7540
Willy Tarreau419ead82014-09-16 13:41:21 +02007541 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007542 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007543 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007544 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007545 struct act_rule *trule;
7546 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007547 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007548 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007549 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007550
Willy Tarreau050536d2012-10-04 08:47:34 +02007551 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007552 /* proxy ID not set, use automatic numbering with first
7553 * spare entry starting with next_pxid.
7554 */
7555 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7556 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7557 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007558 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007559 next_pxid++;
7560
Willy Tarreau55ea7572007-06-17 19:56:27 +02007561
Willy Tarreaubaaee002006-06-26 02:48:02 +02007562 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007563 /* ensure we don't keep listeners uselessly bound */
7564 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007565 free((void *)curproxy->table.peers.name);
7566 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007567 continue;
7568 }
7569
Willy Tarreau102df612014-05-07 23:56:38 +02007570 /* Check multi-process mode compatibility for the current proxy */
7571
7572 if (curproxy->bind_proc) {
7573 /* an explicit bind-process was specified, let's check how many
7574 * processes remain.
7575 */
David Carliere6c39412015-07-02 07:00:17 +00007576 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007577
7578 curproxy->bind_proc &= nbits(global.nbproc);
7579 if (!curproxy->bind_proc && nbproc == 1) {
7580 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);
7581 curproxy->bind_proc = 1;
7582 }
7583 else if (!curproxy->bind_proc && nbproc > 1) {
7584 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);
7585 curproxy->bind_proc = 0;
7586 }
7587 }
7588
Willy Tarreau3d209582014-05-09 17:06:11 +02007589 /* check and reduce the bind-proc of each listener */
7590 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7591 unsigned long mask;
7592
7593 if (!bind_conf->bind_proc)
7594 continue;
7595
7596 mask = nbits(global.nbproc);
7597 if (curproxy->bind_proc)
7598 mask &= curproxy->bind_proc;
7599 /* mask cannot be null here thanks to the previous checks */
7600
David Carliere6c39412015-07-02 07:00:17 +00007601 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007602 bind_conf->bind_proc &= mask;
7603
7604 if (!bind_conf->bind_proc && nbproc == 1) {
7605 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",
7606 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7607 bind_conf->bind_proc = mask & ~(mask - 1);
7608 }
7609 else if (!bind_conf->bind_proc && nbproc > 1) {
7610 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",
7611 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7612 bind_conf->bind_proc = 0;
7613 }
7614 }
7615
Willy Tarreauff01a212009-03-15 13:46:16 +01007616 switch (curproxy->mode) {
7617 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007618 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007619 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007620 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7621 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007622 cfgerr++;
7623 }
7624
7625 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007626 Warning("config : servers will be ignored for %s '%s'.\n",
7627 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007628 break;
7629
7630 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007631 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007632 break;
7633
7634 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007635 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007636 break;
7637 }
7638
Willy Tarreauf3934b82015-08-11 11:36:45 +02007639 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7640 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7641 proxy_type_str(curproxy), curproxy->id);
7642 err_code |= ERR_WARN;
7643 }
7644
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007645 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007646 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007647 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007648 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7649 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007650 cfgerr++;
7651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007652#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007653 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007654 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7655 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007656 cfgerr++;
7657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007658#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007659 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007660 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7661 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007662 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007663 }
7664 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007665 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007666 /* If no LB algo is set in a backend, and we're not in
7667 * transparent mode, dispatch mode nor proxy mode, we
7668 * want to use balance roundrobin by default.
7669 */
7670 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7671 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007672 }
7673 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007674
Willy Tarreau1620ec32011-08-06 17:05:02 +02007675 if (curproxy->options & PR_O_DISPATCH)
7676 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7677 else if (curproxy->options & PR_O_HTTP_PROXY)
7678 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7679 else if (curproxy->options & PR_O_TRANSP)
7680 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007681
Willy Tarreau1620ec32011-08-06 17:05:02 +02007682 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7683 if (curproxy->options & PR_O_DISABLE404) {
7684 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7685 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7686 err_code |= ERR_WARN;
7687 curproxy->options &= ~PR_O_DISABLE404;
7688 }
7689 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7690 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7691 "send-state", proxy_type_str(curproxy), curproxy->id);
7692 err_code |= ERR_WARN;
7693 curproxy->options &= ~PR_O2_CHK_SNDST;
7694 }
Willy Tarreauef781042010-01-27 11:53:01 +01007695 }
7696
Simon Horman98637e52014-06-20 12:30:16 +09007697 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7698 if (!global.external_check) {
7699 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7700 curproxy->id, "option external-check");
7701 cfgerr++;
7702 }
7703 if (!curproxy->check_command) {
7704 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7705 curproxy->id, "option external-check");
7706 cfgerr++;
7707 }
7708 }
7709
Simon Horman64e34162015-02-06 11:11:57 +09007710 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007711 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7712 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007713 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7714 "'email-alert myhostname', or 'email-alert to' "
7715 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007716 "to be present).\n",
7717 proxy_type_str(curproxy), curproxy->id);
7718 err_code |= ERR_WARN;
7719 free_email_alert(curproxy);
7720 }
7721 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007722 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007723 }
7724
Simon Horman98637e52014-06-20 12:30:16 +09007725 if (curproxy->check_command) {
7726 int clear = 0;
7727 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7728 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7729 "external-check command", proxy_type_str(curproxy), curproxy->id);
7730 err_code |= ERR_WARN;
7731 clear = 1;
7732 }
7733 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007734 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007735 curproxy->id, "external-check command");
7736 cfgerr++;
7737 }
7738 if (clear) {
7739 free(curproxy->check_command);
7740 curproxy->check_command = NULL;
7741 }
7742 }
7743
7744 if (curproxy->check_path) {
7745 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7746 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7747 "external-check path", proxy_type_str(curproxy), curproxy->id);
7748 err_code |= ERR_WARN;
7749 free(curproxy->check_path);
7750 curproxy->check_path = NULL;
7751 }
7752 }
7753
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007754 /* if a default backend was specified, let's find it */
7755 if (curproxy->defbe.name) {
7756 struct proxy *target;
7757
Willy Tarreauafb39922015-05-26 12:04:09 +02007758 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007759 if (!target) {
7760 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7761 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007762 cfgerr++;
7763 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007764 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7765 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007766 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007767 } else if (target->mode != curproxy->mode &&
7768 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7769
7770 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7771 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7772 curproxy->conf.file, curproxy->conf.line,
7773 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7774 target->conf.file, target->conf.line);
7775 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007776 } else {
7777 free(curproxy->defbe.name);
7778 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007779
7780 /* Emit a warning if this proxy also has some servers */
7781 if (curproxy->srv) {
7782 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7783 curproxy->id);
7784 err_code |= ERR_WARN;
7785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007786 }
7787 }
7788
Willy Tarreau55ea7572007-06-17 19:56:27 +02007789 /* find the target proxy for 'use_backend' rules */
7790 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007791 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007792 struct logformat_node *node;
7793 char *pxname;
7794
7795 /* Try to parse the string as a log format expression. If the result
7796 * of the parsing is only one entry containing a simple string, then
7797 * it's a standard string corresponding to a static rule, thus the
7798 * parsing is cancelled and be.name is restored to be resolved.
7799 */
7800 pxname = rule->be.name;
7801 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007802 curproxy->conf.args.ctx = ARGC_UBK;
7803 curproxy->conf.args.file = rule->file;
7804 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007805 err = NULL;
7806 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7807 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7808 rule->file, rule->line, pxname, err);
7809 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007810 cfgerr++;
7811 continue;
7812 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007813 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7814
7815 if (!LIST_ISEMPTY(&rule->be.expr)) {
7816 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7817 rule->dynamic = 1;
7818 free(pxname);
7819 continue;
7820 }
7821 /* simple string: free the expression and fall back to static rule */
7822 free(node->arg);
7823 free(node);
7824 }
7825
7826 rule->dynamic = 0;
7827 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007828
Willy Tarreauafb39922015-05-26 12:04:09 +02007829 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007830 if (!target) {
7831 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7832 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007833 cfgerr++;
7834 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007835 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7836 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007837 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007838 } else if (target->mode != curproxy->mode &&
7839 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7840
7841 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7842 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7843 curproxy->conf.file, curproxy->conf.line,
7844 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7845 target->conf.file, target->conf.line);
7846 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007847 } else {
7848 free((void *)rule->be.name);
7849 rule->be.backend = target;
7850 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007851 }
7852
Willy Tarreau64ab6072014-09-16 12:17:36 +02007853 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007854 list_for_each_entry(srule, &curproxy->server_rules, list) {
7855 struct server *target = findserver(curproxy, srule->srv.name);
7856
7857 if (!target) {
7858 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7859 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7860 cfgerr++;
7861 continue;
7862 }
7863 free((void *)srule->srv.name);
7864 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007865 }
7866
Emeric Brunb982a3d2010-01-04 15:45:53 +01007867 /* find the target table for 'stick' rules */
7868 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7869 struct proxy *target;
7870
Emeric Brun1d33b292010-01-04 15:47:17 +01007871 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7872 if (mrule->flags & STK_IS_STORE)
7873 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7874
Emeric Brunb982a3d2010-01-04 15:45:53 +01007875 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007876 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007877 else
7878 target = curproxy;
7879
7880 if (!target) {
7881 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7882 curproxy->id, mrule->table.name);
7883 cfgerr++;
7884 }
7885 else if (target->table.size == 0) {
7886 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7887 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7888 cfgerr++;
7889 }
Willy Tarreau12785782012-04-27 21:37:17 +02007890 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7891 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007892 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7893 cfgerr++;
7894 }
7895 else {
7896 free((void *)mrule->table.name);
7897 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007898 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007899 }
7900 }
7901
7902 /* find the target table for 'store response' rules */
7903 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7904 struct proxy *target;
7905
Emeric Brun1d33b292010-01-04 15:47:17 +01007906 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7907
Emeric Brunb982a3d2010-01-04 15:45:53 +01007908 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007909 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007910 else
7911 target = curproxy;
7912
7913 if (!target) {
7914 Alert("Proxy '%s': unable to find store table '%s'.\n",
7915 curproxy->id, mrule->table.name);
7916 cfgerr++;
7917 }
7918 else if (target->table.size == 0) {
7919 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7920 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7921 cfgerr++;
7922 }
Willy Tarreau12785782012-04-27 21:37:17 +02007923 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7924 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007925 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7926 cfgerr++;
7927 }
7928 else {
7929 free((void *)mrule->table.name);
7930 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007931 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007932 }
7933 }
7934
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007935 /* find the target table for 'tcp-request' layer 4 rules */
7936 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7937 struct proxy *target;
7938
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007939 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007940 continue;
7941
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007942 if (trule->arg.trk_ctr.table.n)
7943 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007944 else
7945 target = curproxy;
7946
7947 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007948 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007949 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007950 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007951 cfgerr++;
7952 }
7953 else if (target->table.size == 0) {
7954 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007955 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007956 cfgerr++;
7957 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007958 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007959 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007960 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007961 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007962 cfgerr++;
7963 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007964 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007965 free(trule->arg.trk_ctr.table.n);
7966 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007967 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007968 * to pass a list of counters to track and allocate them right here using
7969 * stktable_alloc_data_type().
7970 */
7971 }
7972 }
7973
Willy Tarreau620408f2016-10-21 16:37:51 +02007974 /* find the target table for 'tcp-request' layer 5 rules */
7975 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7976 struct proxy *target;
7977
7978 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7979 continue;
7980
7981 if (trule->arg.trk_ctr.table.n)
7982 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7983 else
7984 target = curproxy;
7985
7986 if (!target) {
7987 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7988 curproxy->id, trule->arg.trk_ctr.table.n,
7989 tcp_trk_idx(trule->action));
7990 cfgerr++;
7991 }
7992 else if (target->table.size == 0) {
7993 Alert("Proxy '%s': table '%s' used but not configured.\n",
7994 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7995 cfgerr++;
7996 }
7997 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7998 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7999 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
8000 tcp_trk_idx(trule->action));
8001 cfgerr++;
8002 }
8003 else {
8004 free(trule->arg.trk_ctr.table.n);
8005 trule->arg.trk_ctr.table.t = &target->table;
8006 /* Note: if we decide to enhance the track-sc syntax, we may be able
8007 * to pass a list of counters to track and allocate them right here using
8008 * stktable_alloc_data_type().
8009 */
8010 }
8011 }
8012
Willy Tarreaud1f96522010-08-03 19:34:32 +02008013 /* find the target table for 'tcp-request' layer 6 rules */
8014 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
8015 struct proxy *target;
8016
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008017 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02008018 continue;
8019
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008020 if (trule->arg.trk_ctr.table.n)
8021 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008022 else
8023 target = curproxy;
8024
8025 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02008026 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008027 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008028 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02008029 cfgerr++;
8030 }
8031 else if (target->table.size == 0) {
8032 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008033 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02008034 cfgerr++;
8035 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008036 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01008037 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008038 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01008039 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01008040 cfgerr++;
8041 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02008042 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008043 free(trule->arg.trk_ctr.table.n);
8044 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02008045 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02008046 * to pass a list of counters to track and allocate them right here using
8047 * stktable_alloc_data_type().
8048 */
8049 }
8050 }
8051
Baptiste Assmanne9544932015-11-03 23:31:35 +01008052 /* parse http-request capture rules to ensure id really exists */
8053 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8054 if (hrqrule->action != ACT_CUSTOM ||
8055 hrqrule->action_ptr != http_action_req_capture_by_id)
8056 continue;
8057
8058 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
8059 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
8060 curproxy->id, hrqrule->arg.capid.idx);
8061 cfgerr++;
8062 }
8063 }
8064
8065 /* parse http-response capture rules to ensure id really exists */
8066 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8067 if (hrqrule->action != ACT_CUSTOM ||
8068 hrqrule->action_ptr != http_action_res_capture_by_id)
8069 continue;
8070
8071 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
8072 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
8073 curproxy->id, hrqrule->arg.capid.idx);
8074 cfgerr++;
8075 }
8076 }
8077
Willy Tarreau09448f72014-06-25 18:12:15 +02008078 /* find the target table for 'http-request' layer 7 rules */
8079 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
8080 struct proxy *target;
8081
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008082 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02008083 continue;
8084
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008085 if (hrqrule->arg.trk_ctr.table.n)
8086 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02008087 else
8088 target = curproxy;
8089
8090 if (!target) {
8091 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008092 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008093 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008094 cfgerr++;
8095 }
8096 else if (target->table.size == 0) {
8097 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008098 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02008099 cfgerr++;
8100 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008101 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02008102 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008103 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08008104 http_trk_idx(hrqrule->action));
8105 cfgerr++;
8106 }
8107 else {
8108 free(hrqrule->arg.trk_ctr.table.n);
8109 hrqrule->arg.trk_ctr.table.t = &target->table;
8110 /* Note: if we decide to enhance the track-sc syntax, we may be able
8111 * to pass a list of counters to track and allocate them right here using
8112 * stktable_alloc_data_type().
8113 */
8114 }
8115 }
8116
8117 /* find the target table for 'http-response' layer 7 rules */
8118 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8119 struct proxy *target;
8120
8121 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8122 continue;
8123
8124 if (hrqrule->arg.trk_ctr.table.n)
8125 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8126 else
8127 target = curproxy;
8128
8129 if (!target) {
8130 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8131 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8132 http_trk_idx(hrqrule->action));
8133 cfgerr++;
8134 }
8135 else if (target->table.size == 0) {
8136 Alert("Proxy '%s': table '%s' used but not configured.\n",
8137 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8138 cfgerr++;
8139 }
8140 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8141 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8142 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8143 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008144 cfgerr++;
8145 }
8146 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008147 free(hrqrule->arg.trk_ctr.table.n);
8148 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008149 /* Note: if we decide to enhance the track-sc syntax, we may be able
8150 * to pass a list of counters to track and allocate them right here using
8151 * stktable_alloc_data_type().
8152 */
8153 }
8154 }
8155
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008156 /* move any "block" rules at the beginning of the http-request rules */
8157 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8158 /* insert block_rules into http_req_rules at the beginning */
8159 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8160 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8161 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8162 curproxy->http_req_rules.n = curproxy->block_rules.n;
8163 LIST_INIT(&curproxy->block_rules);
8164 }
8165
Emeric Brun32da3c42010-09-23 18:39:19 +02008166 if (curproxy->table.peers.name) {
8167 struct peers *curpeers = peers;
8168
8169 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8170 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8171 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008172 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008173 break;
8174 }
8175 }
8176
8177 if (!curpeers) {
8178 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8179 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008180 free((void *)curproxy->table.peers.name);
8181 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008182 cfgerr++;
8183 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008184 else if (curpeers->state == PR_STSTOPPED) {
8185 /* silently disable this peers section */
8186 curproxy->table.peers.p = NULL;
8187 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008188 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008189 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8190 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008191 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008192 cfgerr++;
8193 }
8194 }
8195
Simon Horman9dc49962015-01-30 11:22:59 +09008196
8197 if (curproxy->email_alert.mailers.name) {
8198 struct mailers *curmailers = mailers;
8199
8200 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8201 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8202 free(curproxy->email_alert.mailers.name);
8203 curproxy->email_alert.mailers.m = curmailers;
8204 curmailers->users++;
8205 break;
8206 }
8207 }
8208
8209 if (!curmailers) {
8210 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8211 curproxy->id, curproxy->email_alert.mailers.name);
8212 free_email_alert(curproxy);
8213 cfgerr++;
8214 }
8215 }
8216
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008217 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008218 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008219 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8220 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8221 "proxy", curproxy->id);
8222 cfgerr++;
8223 goto out_uri_auth_compat;
8224 }
8225
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008226 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008227 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008228 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008229 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008230
Willy Tarreau95fa4692010-02-01 13:05:50 +01008231 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8232 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008233
8234 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008235 uri_auth_compat_req[i++] = "realm";
8236 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8237 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008238
Willy Tarreau95fa4692010-02-01 13:05:50 +01008239 uri_auth_compat_req[i++] = "unless";
8240 uri_auth_compat_req[i++] = "{";
8241 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8242 uri_auth_compat_req[i++] = "}";
8243 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008244
Willy Tarreauff011f22011-01-06 17:51:27 +01008245 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8246 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008247 cfgerr++;
8248 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008249 }
8250
Willy Tarreauff011f22011-01-06 17:51:27 +01008251 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008252
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008253 if (curproxy->uri_auth->auth_realm) {
8254 free(curproxy->uri_auth->auth_realm);
8255 curproxy->uri_auth->auth_realm = NULL;
8256 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008257
8258 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008259 }
8260out_uri_auth_compat:
8261
Dragan Dosen43885c72015-10-01 13:18:13 +02008262 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008263 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008264 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8265 if (!curproxy->conf.logformat_sd_string) {
8266 /* set the default logformat_sd_string */
8267 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8268 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008269 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008270 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008271 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008272
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008273 /* compile the log format */
8274 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008275 if (curproxy->conf.logformat_string != default_http_log_format &&
8276 curproxy->conf.logformat_string != default_tcp_log_format &&
8277 curproxy->conf.logformat_string != clf_http_log_format)
8278 free(curproxy->conf.logformat_string);
8279 curproxy->conf.logformat_string = NULL;
8280 free(curproxy->conf.lfs_file);
8281 curproxy->conf.lfs_file = NULL;
8282 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008283
8284 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8285 free(curproxy->conf.logformat_sd_string);
8286 curproxy->conf.logformat_sd_string = NULL;
8287 free(curproxy->conf.lfsd_file);
8288 curproxy->conf.lfsd_file = NULL;
8289 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008290 }
8291
Willy Tarreau62a61232013-04-12 18:13:46 +02008292 if (curproxy->conf.logformat_string) {
8293 curproxy->conf.args.ctx = ARGC_LOG;
8294 curproxy->conf.args.file = curproxy->conf.lfs_file;
8295 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008296 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008297 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008298 SMP_VAL_FE_LOG_END, &err)) {
8299 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8300 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8301 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008302 cfgerr++;
8303 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008304 curproxy->conf.args.file = NULL;
8305 curproxy->conf.args.line = 0;
8306 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008307
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008308 if (curproxy->conf.logformat_sd_string) {
8309 curproxy->conf.args.ctx = ARGC_LOGSD;
8310 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8311 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008312 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008313 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 +01008314 SMP_VAL_FE_LOG_END, &err)) {
8315 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8316 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8317 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008318 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008319 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8320 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8321 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8322 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008323 cfgerr++;
8324 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008325 curproxy->conf.args.file = NULL;
8326 curproxy->conf.args.line = 0;
8327 }
8328
Willy Tarreau62a61232013-04-12 18:13:46 +02008329 if (curproxy->conf.uniqueid_format_string) {
8330 curproxy->conf.args.ctx = ARGC_UIF;
8331 curproxy->conf.args.file = curproxy->conf.uif_file;
8332 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008333 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008334 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 +01008335 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8336 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8337 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8338 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008339 cfgerr++;
8340 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008341 curproxy->conf.args.file = NULL;
8342 curproxy->conf.args.line = 0;
8343 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008344
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008345 /* only now we can check if some args remain unresolved.
8346 * This must be done after the users and groups resolution.
8347 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008348 cfgerr += smp_resolve_args(curproxy);
8349 if (!cfgerr)
8350 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008351
Willy Tarreau2738a142006-07-08 17:28:09 +02008352 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008353 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008354 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008355 (!curproxy->timeout.connect ||
8356 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008357 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008358 " | While not properly invalid, you will certainly encounter various problems\n"
8359 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008360 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008361 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008362 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008363 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008364
Willy Tarreau1fa31262007-12-03 00:36:16 +01008365 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8366 * We must still support older configurations, so let's find out whether those
8367 * parameters have been set or must be copied from contimeouts.
8368 */
8369 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008370 if (!curproxy->timeout.tarpit ||
8371 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008372 /* tarpit timeout not set. We search in the following order:
8373 * default.tarpit, curr.connect, default.connect.
8374 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008375 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008376 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008377 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008378 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008379 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008380 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008381 }
8382 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008383 (!curproxy->timeout.queue ||
8384 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008385 /* queue timeout not set. We search in the following order:
8386 * default.queue, curr.connect, default.connect.
8387 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008388 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008389 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008390 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008391 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008392 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008393 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008394 }
8395 }
8396
Willy Tarreau1620ec32011-08-06 17:05:02 +02008397 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008398 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008399 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008400 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008401 }
8402
Willy Tarreau215663d2014-06-13 18:30:23 +02008403 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8404 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8405 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8406 proxy_type_str(curproxy), curproxy->id);
8407 err_code |= ERR_WARN;
8408 }
8409
Willy Tarreau193b8c62012-11-22 00:17:38 +01008410 /* ensure that cookie capture length is not too large */
8411 if (curproxy->capture_len >= global.tune.cookie_len) {
8412 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8413 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8414 err_code |= ERR_WARN;
8415 curproxy->capture_len = global.tune.cookie_len - 1;
8416 }
8417
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008418 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008419 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008420 curproxy->req_cap_pool = create_pool("ptrcap",
8421 curproxy->nb_req_cap * sizeof(char *),
8422 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008423 }
8424
8425 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008426 curproxy->rsp_cap_pool = create_pool("ptrcap",
8427 curproxy->nb_rsp_cap * sizeof(char *),
8428 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008429 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008430
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008431 switch (curproxy->load_server_state_from_file) {
8432 case PR_SRV_STATE_FILE_UNSPEC:
8433 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8434 break;
8435 case PR_SRV_STATE_FILE_GLOBAL:
8436 if (!global.server_state_file) {
8437 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",
8438 curproxy->id);
8439 err_code |= ERR_WARN;
8440 }
8441 break;
8442 }
8443
Willy Tarreaubaaee002006-06-26 02:48:02 +02008444 /* first, we will invert the servers list order */
8445 newsrv = NULL;
8446 while (curproxy->srv) {
8447 struct server *next;
8448
8449 next = curproxy->srv->next;
8450 curproxy->srv->next = newsrv;
8451 newsrv = curproxy->srv;
8452 if (!next)
8453 break;
8454 curproxy->srv = next;
8455 }
8456
Willy Tarreau17edc812014-01-03 12:14:34 +01008457 /* Check that no server name conflicts. This causes trouble in the stats.
8458 * We only emit a warning for the first conflict affecting each server,
8459 * in order to avoid combinatory explosion if all servers have the same
8460 * name. We do that only for servers which do not have an explicit ID,
8461 * because these IDs were made also for distinguishing them and we don't
8462 * want to annoy people who correctly manage them.
8463 */
8464 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8465 struct server *other_srv;
8466
8467 if (newsrv->puid)
8468 continue;
8469
8470 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8471 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8472 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8473 newsrv->conf.file, newsrv->conf.line,
8474 proxy_type_str(curproxy), curproxy->id,
8475 newsrv->id, other_srv->conf.line);
8476 break;
8477 }
8478 }
8479 }
8480
Willy Tarreaudd701652010-05-25 23:03:02 +02008481 /* assign automatic UIDs to servers which don't have one yet */
8482 next_id = 1;
8483 newsrv = curproxy->srv;
8484 while (newsrv != NULL) {
8485 if (!newsrv->puid) {
8486 /* server ID not set, use automatic numbering with first
8487 * spare entry starting with next_svid.
8488 */
8489 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8490 newsrv->conf.id.key = newsrv->puid = next_id;
8491 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8492 }
8493 next_id++;
8494 newsrv = newsrv->next;
8495 }
8496
Willy Tarreau20697042007-11-15 23:26:18 +01008497 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008498 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008499
Willy Tarreau62c3be22012-01-20 13:12:32 +01008500 /*
8501 * If this server supports a maxconn parameter, it needs a dedicated
8502 * tasks to fill the emptied slots when a connection leaves.
8503 * Also, resolve deferred tracking dependency if needed.
8504 */
8505 newsrv = curproxy->srv;
8506 while (newsrv != NULL) {
8507 if (newsrv->minconn > newsrv->maxconn) {
8508 /* Only 'minconn' was specified, or it was higher than or equal
8509 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8510 * this will avoid further useless expensive computations.
8511 */
8512 newsrv->maxconn = newsrv->minconn;
8513 } else if (newsrv->maxconn && !newsrv->minconn) {
8514 /* minconn was not specified, so we set it to maxconn */
8515 newsrv->minconn = newsrv->maxconn;
8516 }
8517
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008518#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008519 if (newsrv->use_ssl || newsrv->check.use_ssl)
8520 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008521#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008522
Willy Tarreau2f075e92013-12-03 11:11:34 +01008523 /* set the check type on the server */
8524 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8525
Willy Tarreau62c3be22012-01-20 13:12:32 +01008526 if (newsrv->trackit) {
8527 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008528 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008529 char *pname, *sname;
8530
8531 pname = newsrv->trackit;
8532 sname = strrchr(pname, '/');
8533
8534 if (sname)
8535 *sname++ = '\0';
8536 else {
8537 sname = pname;
8538 pname = NULL;
8539 }
8540
8541 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008542 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008543 if (!px) {
8544 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8545 proxy_type_str(curproxy), curproxy->id,
8546 newsrv->id, pname);
8547 cfgerr++;
8548 goto next_srv;
8549 }
8550 } else
8551 px = curproxy;
8552
8553 srv = findserver(px, sname);
8554 if (!srv) {
8555 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8556 proxy_type_str(curproxy), curproxy->id,
8557 newsrv->id, sname);
8558 cfgerr++;
8559 goto next_srv;
8560 }
8561
Willy Tarreau32091232014-05-16 13:52:00 +02008562 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8563 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8564 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008565 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008566 "tracking as it does not have any check nor agent enabled.\n",
8567 proxy_type_str(curproxy), curproxy->id,
8568 newsrv->id, px->id, srv->id);
8569 cfgerr++;
8570 goto next_srv;
8571 }
8572
8573 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8574
8575 if (loop) {
8576 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8577 "belongs to a tracking chain looping back to %s/%s.\n",
8578 proxy_type_str(curproxy), curproxy->id,
8579 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008580 cfgerr++;
8581 goto next_srv;
8582 }
8583
8584 if (curproxy != px &&
8585 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8586 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8587 "tracking: disable-on-404 option inconsistency.\n",
8588 proxy_type_str(curproxy), curproxy->id,
8589 newsrv->id, px->id, srv->id);
8590 cfgerr++;
8591 goto next_srv;
8592 }
8593
Willy Tarreau62c3be22012-01-20 13:12:32 +01008594 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008595 newsrv->tracknext = srv->trackers;
8596 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008597
8598 free(newsrv->trackit);
8599 newsrv->trackit = NULL;
8600 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008601
8602 /*
8603 * resolve server's resolvers name and update the resolvers pointer
8604 * accordingly
8605 */
8606 if (newsrv->resolvers_id) {
8607 struct dns_resolvers *curr_resolvers;
8608 int found;
8609
8610 found = 0;
8611 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8612 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8613 found = 1;
8614 break;
8615 }
8616 }
8617
8618 if (!found) {
8619 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8620 proxy_type_str(curproxy), curproxy->id,
8621 newsrv->id, newsrv->resolvers_id);
8622 cfgerr++;
8623 } else {
8624 free(newsrv->resolvers_id);
8625 newsrv->resolvers_id = NULL;
8626 if (newsrv->resolution)
8627 newsrv->resolution->resolvers = curr_resolvers;
8628 }
8629 }
8630 else {
8631 /* if no resolvers section associated to this server
8632 * we can clean up the associated resolution structure
8633 */
8634 if (newsrv->resolution) {
8635 free(newsrv->resolution->hostname_dn);
8636 newsrv->resolution->hostname_dn = NULL;
8637 free(newsrv->resolution);
8638 newsrv->resolution = NULL;
8639 }
8640 }
8641
Willy Tarreau62c3be22012-01-20 13:12:32 +01008642 next_srv:
8643 newsrv = newsrv->next;
8644 }
8645
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008646 /* We have to initialize the server lookup mechanism depending
8647 * on what LB algorithm was choosen.
8648 */
8649
8650 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8651 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8652 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008653 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8654 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8655 init_server_map(curproxy);
8656 } else {
8657 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8658 fwrr_init_server_groups(curproxy);
8659 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008660 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008661
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008662 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008663 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8664 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8665 fwlc_init_server_tree(curproxy);
8666 } else {
8667 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8668 fas_init_server_tree(curproxy);
8669 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008670 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008671
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008672 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008673 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8674 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8675 chash_init_server_tree(curproxy);
8676 } else {
8677 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8678 init_server_map(curproxy);
8679 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008680 break;
8681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008682
8683 if (curproxy->options & PR_O_LOGASAP)
8684 curproxy->to_log &= ~LW_BYTES;
8685
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008686 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008687 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8688 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008689 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8690 proxy_type_str(curproxy), curproxy->id);
8691 err_code |= ERR_WARN;
8692 }
8693
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008694 if (curproxy->mode != PR_MODE_HTTP) {
8695 int optnum;
8696
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008697 if (curproxy->uri_auth) {
8698 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8699 proxy_type_str(curproxy), curproxy->id);
8700 err_code |= ERR_WARN;
8701 curproxy->uri_auth = NULL;
8702 }
8703
Willy Tarreau87cf5142011-08-19 22:57:24 +02008704 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008705 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8706 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8707 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008708 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008709 }
8710
8711 if (curproxy->options & PR_O_ORGTO) {
8712 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8713 "originalto", proxy_type_str(curproxy), curproxy->id);
8714 err_code |= ERR_WARN;
8715 curproxy->options &= ~PR_O_ORGTO;
8716 }
8717
8718 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8719 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8720 (curproxy->cap & cfg_opts[optnum].cap) &&
8721 (curproxy->options & cfg_opts[optnum].val)) {
8722 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8723 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8724 err_code |= ERR_WARN;
8725 curproxy->options &= ~cfg_opts[optnum].val;
8726 }
8727 }
8728
8729 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8730 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8731 (curproxy->cap & cfg_opts2[optnum].cap) &&
8732 (curproxy->options2 & cfg_opts2[optnum].val)) {
8733 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8734 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8735 err_code |= ERR_WARN;
8736 curproxy->options2 &= ~cfg_opts2[optnum].val;
8737 }
8738 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008739
Willy Tarreau29fbe512015-08-20 19:35:14 +02008740#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008741 if (curproxy->conn_src.bind_hdr_occ) {
8742 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008743 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008744 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008745 err_code |= ERR_WARN;
8746 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008747#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008748 }
8749
Willy Tarreaubaaee002006-06-26 02:48:02 +02008750 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008751 * ensure that we're not cross-dressing a TCP server into HTTP.
8752 */
8753 newsrv = curproxy->srv;
8754 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008755 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008756 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8757 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008758 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008759 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008760
Willy Tarreau0cec3312011-10-31 13:49:26 +01008761 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8762 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8763 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8764 err_code |= ERR_WARN;
8765 }
8766
Willy Tarreauc93cd162014-05-13 15:54:22 +02008767 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008768 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8769 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8770 err_code |= ERR_WARN;
8771 }
8772
Willy Tarreau29fbe512015-08-20 19:35:14 +02008773#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008774 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8775 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008776 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 +01008777 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008778 err_code |= ERR_WARN;
8779 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008780#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008781 newsrv = newsrv->next;
8782 }
8783
Willy Tarreaue42bd962014-09-16 16:21:19 +02008784 /* check if we have a frontend with "tcp-request content" looking at L7
8785 * with no inspect-delay
8786 */
8787 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8788 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008789 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008790 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008791 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008792 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008793 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008794 break;
8795 }
8796
8797 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8798 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8799 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8800 " This means that these rules will randomly find their contents. This can be fixed by"
8801 " setting the tcp-request inspect-delay.\n",
8802 proxy_type_str(curproxy), curproxy->id);
8803 err_code |= ERR_WARN;
8804 }
8805 }
8806
Christopher Fauletd7c91962015-04-30 11:48:27 +02008807 /* Check filter configuration, if any */
8808 cfgerr += flt_check(curproxy);
8809
Willy Tarreauc1a21672009-08-16 22:37:44 +02008810 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008811 if (!curproxy->accept)
8812 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008813
Willy Tarreauc1a21672009-08-16 22:37:44 +02008814 if (curproxy->tcp_req.inspect_delay ||
8815 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008816 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008817
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008818 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008819 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008820 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008821 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008822
8823 /* both TCP and HTTP must check switching rules */
8824 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008825
8826 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008827 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008828 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8829 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008830 if (curproxy->mode == PR_MODE_HTTP) {
8831 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8832 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8833 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008834 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008835 }
8836
8837 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008838 if (curproxy->tcp_req.inspect_delay ||
8839 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8840 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8841
Emeric Brun97679e72010-09-23 17:56:44 +02008842 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8843 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8844
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008845 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008846 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008847 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008848 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008849
8850 /* If the backend does requires RDP cookie persistence, we have to
8851 * enable the corresponding analyser.
8852 */
8853 if (curproxy->options2 & PR_O2_RDPC_PRST)
8854 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008855
8856 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008857 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008858 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8859 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008860 if (curproxy->mode == PR_MODE_HTTP) {
8861 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8862 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8863 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008864 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008865 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008866 }
8867
8868 /***********************************************************/
8869 /* At this point, target names have already been resolved. */
8870 /***********************************************************/
8871
8872 /* Check multi-process mode compatibility */
8873
8874 if (global.nbproc > 1 && global.stats_fe) {
8875 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8876 unsigned long mask;
8877
8878 mask = nbits(global.nbproc);
8879 if (global.stats_fe->bind_proc)
8880 mask &= global.stats_fe->bind_proc;
8881
8882 if (bind_conf->bind_proc)
8883 mask &= bind_conf->bind_proc;
8884
8885 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008886 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008887 break;
8888 }
8889 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8890 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");
8891 }
8892 }
8893
8894 /* Make each frontend inherit bind-process from its listeners when not specified. */
8895 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8896 if (curproxy->bind_proc)
8897 continue;
8898
8899 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8900 unsigned long mask;
8901
Willy Tarreaue428b082015-05-04 21:57:58 +02008902 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008903 curproxy->bind_proc |= mask;
8904 }
8905
8906 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008907 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008908 }
8909
8910 if (global.stats_fe) {
8911 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8912 unsigned long mask;
8913
Cyril Bonté06181952016-02-24 00:14:54 +01008914 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008915 global.stats_fe->bind_proc |= mask;
8916 }
8917 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008918 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008919 }
8920
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008921 /* propagate bindings from frontends to backends. Don't do it if there
8922 * are any fatal errors as we must not call it with unresolved proxies.
8923 */
8924 if (!cfgerr) {
8925 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8926 if (curproxy->cap & PR_CAP_FE)
8927 propagate_processes(curproxy, NULL);
8928 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008929 }
8930
8931 /* Bind each unbound backend to all processes when not specified. */
8932 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8933 if (curproxy->bind_proc)
8934 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008935 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008936 }
8937
8938 /*******************************************************/
8939 /* At this step, all proxies have a non-null bind_proc */
8940 /*******************************************************/
8941
8942 /* perform the final checks before creating tasks */
8943
8944 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8945 struct listener *listener;
8946 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008947
Emeric Brunc52962f2012-11-15 18:28:02 +01008948#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008949 /* Configure SSL for each bind line.
8950 * Note: if configuration fails at some point, the ->ctx member
8951 * remains NULL so that listeners can later detach.
8952 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008953 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008954 int alloc_ctx;
8955
Emeric Brunc52962f2012-11-15 18:28:02 +01008956 if (!bind_conf->is_ssl) {
8957 if (bind_conf->default_ctx) {
8958 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8959 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8960 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008961 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008962 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008963 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008964 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008965 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008966 cfgerr++;
8967 continue;
8968 }
8969
Emeric Brun8dc60392014-05-09 13:52:00 +02008970 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008971 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008972 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8973 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");
8974 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008975 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008976 cfgerr++;
8977 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008978 }
8979
Emeric Brunfc0421f2012-09-07 17:30:07 +02008980 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008981 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008982
8983 /* initialize CA variables if the certificates generation is enabled */
8984 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008985 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008986#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008987
Willy Tarreaue6b98942007-10-29 01:09:36 +01008988 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008989 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008990 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008991 int nbproc;
8992
8993 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008994 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008995 nbits(global.nbproc));
8996
8997 if (!nbproc) /* no intersection between listener and frontend */
8998 nbproc = 1;
8999
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009000 if (!listener->luid) {
9001 /* listener ID not set, use automatic numbering with first
9002 * spare entry starting with next_luid.
9003 */
9004 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
9005 listener->conf.id.key = listener->luid = next_id;
9006 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009007 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01009008 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02009009
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009010 /* enable separate counters */
9011 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02009012 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01009013 if (!listener->name)
9014 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02009015 }
Willy Tarreau81796be2012-09-22 19:11:47 +02009016
Willy Tarreaue6b98942007-10-29 01:09:36 +01009017 if (curproxy->options & PR_O_TCP_NOLING)
9018 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02009019 if (!listener->maxconn)
9020 listener->maxconn = curproxy->maxconn;
9021 if (!listener->backlog)
9022 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01009023 if (!listener->maxaccept)
9024 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
9025
9026 /* we want to have an optimal behaviour on single process mode to
9027 * maximize the work at once, but in multi-process we want to keep
9028 * some fairness between processes, so we target half of the max
9029 * number of events to be balanced over all the processes the proxy
9030 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
9031 * used to disable the limit.
9032 */
9033 if (listener->maxaccept > 0) {
9034 if (nbproc > 1)
9035 listener->maxaccept = (listener->maxaccept + 1) / 2;
9036 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
9037 }
9038
Willy Tarreau9903f0e2015-04-04 18:50:31 +02009039 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02009040 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02009041 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01009042 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01009043
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009044 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02009045 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02009046
Willy Tarreau620408f2016-10-21 16:37:51 +02009047 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
9048 listener->options |= LI_O_TCP_L5_RULES;
9049
Willy Tarreaude3041d2010-05-31 10:56:17 +02009050 if (curproxy->mon_mask.s_addr)
9051 listener->options |= LI_O_CHK_MONNET;
9052
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009053 /* smart accept mode is automatic in HTTP mode */
9054 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009055 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02009056 !(curproxy->no_options2 & PR_O2_SMARTACC)))
9057 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01009058 }
9059
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009060 /* Release unused SSL configs */
9061 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
9062 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009063 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009064#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02009065 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009066 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009067 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02009068 free(bind_conf->ca_sign_file);
9069 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009070 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02009071 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02009072 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009073 if(bind_conf->keys_ref) {
9074 free(bind_conf->keys_ref->filename);
9075 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02009076 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02009077 free(bind_conf->keys_ref);
9078 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009079#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02009080 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02009081
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02009082 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02009083 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02009084 int count, maxproc = 0;
9085
9086 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00009087 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02009088 if (count > maxproc)
9089 maxproc = count;
9090 }
9091 /* backends have 0, frontends have 1 or more */
9092 if (maxproc != 1)
9093 Warning("Proxy '%s': in multi-process mode, stats will be"
9094 " limited to process assigned to the current request.\n",
9095 curproxy->id);
9096
Willy Tarreau102df612014-05-07 23:56:38 +02009097 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9098 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9099 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009100 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009101 }
Willy Tarreau102df612014-05-07 23:56:38 +02009102 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9103 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9104 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009105 }
9106 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009107
9108 /* create the task associated with the proxy */
9109 curproxy->task = task_new();
9110 if (curproxy->task) {
9111 curproxy->task->context = curproxy;
9112 curproxy->task->process = manage_proxy;
9113 /* no need to queue, it will be done automatically if some
9114 * listener gets limited.
9115 */
9116 curproxy->task->expire = TICK_ETERNITY;
9117 } else {
9118 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9119 curproxy->id);
9120 cfgerr++;
9121 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009122 }
9123
Willy Tarreaufbb78422011-06-05 15:38:35 +02009124 /* automatically compute fullconn if not set. We must not do it in the
9125 * loop above because cross-references are not yet fully resolved.
9126 */
9127 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9128 /* If <fullconn> is not set, let's set it to 10% of the sum of
9129 * the possible incoming frontend's maxconns.
9130 */
9131 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9132 struct proxy *fe;
9133 int total = 0;
9134
9135 /* sum up the number of maxconns of frontends which
9136 * reference this backend at least once or which are
9137 * the same one ('listen').
9138 */
9139 for (fe = proxy; fe; fe = fe->next) {
9140 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009141 int found = 0;
9142
9143 if (!(fe->cap & PR_CAP_FE))
9144 continue;
9145
9146 if (fe == curproxy) /* we're on a "listen" instance */
9147 found = 1;
9148
9149 if (fe->defbe.be == curproxy) /* "default_backend" */
9150 found = 1;
9151
9152 /* check if a "use_backend" rule matches */
9153 if (!found) {
9154 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009155 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009156 found = 1;
9157 break;
9158 }
9159 }
9160 }
9161
Willy Tarreaufbb78422011-06-05 15:38:35 +02009162 /* now we've checked all possible ways to reference a backend
9163 * from a frontend.
9164 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009165 if (!found)
9166 continue;
9167 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009168 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009169 /* we have the sum of the maxconns in <total>. We only
9170 * keep 10% of that sum to set the default fullconn, with
9171 * a hard minimum of 1 (to avoid a divide by zero).
9172 */
9173 curproxy->fullconn = (total + 9) / 10;
9174 if (!curproxy->fullconn)
9175 curproxy->fullconn = 1;
9176 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009177 }
9178
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009179 /*
9180 * Recount currently required checks.
9181 */
9182
9183 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9184 int optnum;
9185
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009186 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9187 if (curproxy->options & cfg_opts[optnum].val)
9188 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009189
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009190 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9191 if (curproxy->options2 & cfg_opts2[optnum].val)
9192 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009193 }
9194
Willy Tarreau0fca4832015-05-01 19:12:05 +02009195 /* compute the required process bindings for the peers */
9196 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9197 if (curproxy->table.peers.p)
9198 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9199
Willy Tarreau122541c2011-09-07 21:24:49 +02009200 if (peers) {
9201 struct peers *curpeers = peers, **last;
9202 struct peer *p, *pb;
9203
Willy Tarreau1e273012015-05-01 19:15:17 +02009204 /* Remove all peers sections which don't have a valid listener,
9205 * which are not used by any table, or which are bound to more
9206 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009207 */
9208 last = &peers;
9209 while (*last) {
9210 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009211
9212 if (curpeers->state == PR_STSTOPPED) {
9213 /* the "disabled" keyword was present */
9214 if (curpeers->peers_fe)
9215 stop_proxy(curpeers->peers_fe);
9216 curpeers->peers_fe = NULL;
9217 }
9218 else if (!curpeers->peers_fe) {
9219 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9220 curpeers->id, localpeer);
9221 }
David Carliere6c39412015-07-02 07:00:17 +00009222 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009223 /* either it's totally stopped or too much used */
9224 if (curpeers->peers_fe->bind_proc) {
9225 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009226 "running in different processes (%d different ones). "
9227 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009228 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009229 cfgerr++;
9230 }
9231 stop_proxy(curpeers->peers_fe);
9232 curpeers->peers_fe = NULL;
9233 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009234 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009235 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009236 last = &curpeers->next;
9237 continue;
9238 }
9239
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009240 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009241 p = curpeers->remote;
9242 while (p) {
9243 pb = p->next;
9244 free(p->id);
9245 free(p);
9246 p = pb;
9247 }
9248
9249 /* Destroy and unlink this curpeers section.
9250 * Note: curpeers is backed up into *last.
9251 */
9252 free(curpeers->id);
9253 curpeers = curpeers->next;
9254 free(*last);
9255 *last = curpeers;
9256 }
9257 }
9258
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009259 /* initialize stick-tables on backend capable proxies. This must not
9260 * be done earlier because the data size may be discovered while parsing
9261 * other proxies.
9262 */
9263 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9264 if (curproxy->state == PR_STSTOPPED)
9265 continue;
9266
9267 if (!stktable_init(&curproxy->table)) {
9268 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9269 cfgerr++;
9270 }
9271 }
9272
Simon Horman0d16a402015-01-30 11:22:58 +09009273 if (mailers) {
9274 struct mailers *curmailers = mailers, **last;
9275 struct mailer *m, *mb;
9276
9277 /* Remove all mailers sections which don't have a valid listener.
9278 * This can happen when a mailers section is never referenced.
9279 */
9280 last = &mailers;
9281 while (*last) {
9282 curmailers = *last;
9283 if (curmailers->users) {
9284 last = &curmailers->next;
9285 continue;
9286 }
9287
9288 Warning("Removing incomplete section 'mailers %s'.\n",
9289 curmailers->id);
9290
9291 m = curmailers->mailer_list;
9292 while (m) {
9293 mb = m->next;
9294 free(m->id);
9295 free(m);
9296 m = mb;
9297 }
9298
9299 /* Destroy and unlink this curmailers section.
9300 * Note: curmailers is backed up into *last.
9301 */
9302 free(curmailers->id);
9303 curmailers = curmailers->next;
9304 free(*last);
9305 *last = curmailers;
9306 }
9307 }
9308
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009309 /* Update server_state_file_name to backend name if backend is supposed to use
9310 * a server-state file locally defined and none has been provided */
9311 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9312 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9313 curproxy->server_state_file_name == NULL)
9314 curproxy->server_state_file_name = strdup(curproxy->id);
9315 }
9316
Willy Tarreau34eb6712011-10-24 18:15:04 +02009317 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009318 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009319 MEM_F_SHARED);
9320
Willy Tarreaubb925012009-07-23 13:36:36 +02009321 if (cfgerr > 0)
9322 err_code |= ERR_ALERT | ERR_FATAL;
9323 out:
9324 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009325}
9326
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009327/*
9328 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9329 * parsing sessions.
9330 */
9331void cfg_register_keywords(struct cfg_kw_list *kwl)
9332{
9333 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9334}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009335
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009336/*
9337 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9338 */
9339void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9340{
9341 LIST_DEL(&kwl->list);
9342 LIST_INIT(&kwl->list);
9343}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009344
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009345/* this function register new section in the haproxy configuration file.
9346 * <section_name> is the name of this new section and <section_parser>
9347 * is the called parser. If two section declaration have the same name,
9348 * only the first declared is used.
9349 */
9350int cfg_register_section(char *section_name,
9351 int (*section_parser)(const char *, int, char **, int))
9352{
9353 struct cfg_section *cs;
9354
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009355 list_for_each_entry(cs, &sections, list) {
9356 if (strcmp(cs->section_name, section_name) == 0) {
9357 Alert("register section '%s': already registered.\n", section_name);
9358 return 0;
9359 }
9360 }
9361
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009362 cs = calloc(1, sizeof(*cs));
9363 if (!cs) {
9364 Alert("register section '%s': out of memory.\n", section_name);
9365 return 0;
9366 }
9367
9368 cs->section_name = section_name;
9369 cs->section_parser = section_parser;
9370
9371 LIST_ADDQ(&sections, &cs->list);
9372
9373 return 1;
9374}
9375
Willy Tarreaubaaee002006-06-26 02:48:02 +02009376/*
David Carlier845efb52015-09-25 11:49:18 +01009377 * free all config section entries
9378 */
9379void cfg_unregister_sections(void)
9380{
9381 struct cfg_section *cs, *ics;
9382
9383 list_for_each_entry_safe(cs, ics, &sections, list) {
9384 LIST_DEL(&cs->list);
9385 free(cs);
9386 }
9387}
9388
Christopher Faulet7110b402016-10-26 11:09:44 +02009389void cfg_backup_sections(struct list *backup_sections)
9390{
9391 struct cfg_section *cs, *ics;
9392
9393 list_for_each_entry_safe(cs, ics, &sections, list) {
9394 LIST_DEL(&cs->list);
9395 LIST_ADDQ(backup_sections, &cs->list);
9396 }
9397}
9398
9399void cfg_restore_sections(struct list *backup_sections)
9400{
9401 struct cfg_section *cs, *ics;
9402
9403 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9404 LIST_DEL(&cs->list);
9405 LIST_ADDQ(&sections, &cs->list);
9406 }
9407}
9408
Willy Tarreau659fbf02016-05-26 17:55:28 +02009409__attribute__((constructor))
9410static void cfgparse_init(void)
9411{
9412 /* Register internal sections */
9413 cfg_register_section("listen", cfg_parse_listen);
9414 cfg_register_section("frontend", cfg_parse_listen);
9415 cfg_register_section("backend", cfg_parse_listen);
9416 cfg_register_section("defaults", cfg_parse_listen);
9417 cfg_register_section("global", cfg_parse_global);
9418 cfg_register_section("userlist", cfg_parse_users);
9419 cfg_register_section("peers", cfg_parse_peers);
9420 cfg_register_section("mailers", cfg_parse_mailers);
9421 cfg_register_section("namespace_list", cfg_parse_netns);
9422 cfg_register_section("resolvers", cfg_parse_resolvers);
9423}
9424
David Carlier845efb52015-09-25 11:49:18 +01009425/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009426 * Local variables:
9427 * c-indent-level: 8
9428 * c-basic-offset: 8
9429 * End:
9430 */