blob: b633a4f37254f22647338c4c8d85ab9c22baada7 [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>
Emeric Brunb982a3d2010-01-04 15:45:53 +010083#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010084#include <proto/task.h>
85#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
87
Willy Tarreauf3c69202006-07-09 16:42:34 +020088/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
89 * ssl-hello-chk option to ensure that the remote server speaks SSL.
90 *
91 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
92 */
93const char sslv3_client_hello_pkt[] = {
94 "\x16" /* ContentType : 0x16 = Hanshake */
95 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
96 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
97 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
98 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
99 "\x03\x00" /* Hello Version : 0x0300 = v3 */
100 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
101 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
102 "\x00" /* Session ID length : empty (no session ID) */
103 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
104 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
105 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
106 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
107 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
108 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
109 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
110 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
111 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
112 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
113 "\x00\x38" "\x00\x39" "\x00\x3A"
114 "\x01" /* Compression Length : 0x01 = 1 byte for types */
115 "\x00" /* Compression Type : 0x00 = NULL compression */
116};
117
Willy Tarreau3842f002009-06-14 11:39:52 +0200118/* various keyword modifiers */
119enum kw_mod {
120 KWM_STD = 0, /* normal */
121 KWM_NO, /* "no" prefixed before the keyword */
122 KWM_DEF, /* "default" prefixed before the keyword */
123};
124
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100125/* permit to store configuration section */
126struct cfg_section {
127 struct list list;
128 char *section_name;
129 int (*section_parser)(const char *, int, char **, int);
130};
131
132/* Used to chain configuration sections definitions. This list
133 * stores struct cfg_section
134 */
135struct list sections = LIST_HEAD_INIT(sections);
136
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100138struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139 const char *name;
140 unsigned int val;
141 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100142 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144};
145
146/* proxy->options */
147static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
150 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
151 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
152 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
153 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
154 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200156 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200157 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100158 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
160 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
161 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100163#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100165#else
166 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100167#endif
168
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100170};
171
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100172/* proxy->options2 */
173static const struct cfg_opt cfg_opts2[] =
174{
175#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
177 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100179#else
180 { "splice-request", 0, 0, 0, 0 },
181 { "splice-response", 0, 0, 0, 0 },
182 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100183#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100184 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
185 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
186 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
187 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
188 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
189 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
190 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
192 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400193 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100194 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200195 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200196 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100197 { NULL, 0, 0, 0 }
198};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199
Willy Tarreau6daf3432008-01-22 16:44:08 +0100200static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
202int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100203int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100204char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200206/* List head of all known configuration keywords */
207static struct cfg_kw_list cfg_keywords = {
208 .list = LIST_HEAD_INIT(cfg_keywords.list)
209};
210
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211/*
212 * converts <str> to a list of listeners which are dynamically allocated.
213 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
214 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
215 * - <port> is a numerical port from 1 to 65535 ;
216 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
217 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
219 * not NULL, it must be a valid pointer to either NULL or a freeable area that
220 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222int 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 +0200223{
224 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 int port, end;
227
228 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200229
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100232 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
234 str = next;
235 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100236 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 *next++ = 0;
238 }
239
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100240 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200241 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200242 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 if (!ss2)
244 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port || !end) {
253 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
254 goto fail;
255 }
256
Emeric Bruned760922010-10-22 17:59:25 +0200257 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
261
262 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100267 else if (ss2->ss_family == AF_UNSPEC) {
268 socklen_t addr_len;
269
270 /* We want to attach to an already bound fd whose number
271 * is in the addr part of ss2 when cast to sockaddr_in.
272 * Note that by definition there is a single listener.
273 * We still have to determine the address family to
274 * register the correct protocol.
275 */
276 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
277 addr_len = sizeof(*ss2);
278 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
279 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
280 goto fail;
281 }
282
283 port = end = get_host_port(ss2);
284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100286 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200287 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100288
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200290 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100291 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200292 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
293 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200294 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau40aa0702013-03-10 23:51:38 +0100296 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200297 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100298 l->state = LI_INIT;
299
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100300 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100302 tcpv4_add_listener(l);
303 }
Emeric Bruned760922010-10-22 17:59:25 +0200304 else if (ss.ss_family == AF_INET6) {
305 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
306 tcpv6_add_listener(l);
307 }
308 else {
Emeric Bruned760922010-10-22 17:59:25 +0200309 uxst_add_listener(l);
310 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200311
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200312 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100313 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200314 } /* end for(port) */
315 } /* end while(next) */
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 fail:
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321}
322
William Lallemand6e62fb62015-04-28 16:55:23 +0200323/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100324 * Report an error in <msg> when there are too many arguments. This version is
325 * intended to be used by keyword parsers so that the message will be included
326 * into the general error message. The index is the current keyword in args.
327 * Return 0 if the number of argument is correct, otherwise build a message and
328 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
329 * message may also be null, it will simply not be produced (useful to check only).
330 * <msg> and <err_code> are only affected on error.
331 */
332int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
333{
334 int i;
335
336 if (!*args[index + maxarg + 1])
337 return 0;
338
339 if (msg) {
340 *msg = NULL;
341 memprintf(msg, "%s", args[0]);
342 for (i = 1; i <= index; i++)
343 memprintf(msg, "%s %s", *msg, args[i]);
344
345 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
346 }
347 if (err_code)
348 *err_code |= ERR_ALERT | ERR_FATAL;
349
350 return 1;
351}
352
353/*
354 * same as too_many_args_idx with a 0 index
355 */
356int too_many_args(int maxarg, char **args, char **msg, int *err_code)
357{
358 return too_many_args_idx(maxarg, 0, args, msg, err_code);
359}
360
361/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200362 * Report a fatal Alert when there is too much arguments
363 * The index is the current keyword in args
364 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
365 * Fill err_code with an ERR_ALERT and an ERR_FATAL
366 */
367int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
368{
369 char *kw = NULL;
370 int i;
371
372 if (!*args[index + maxarg + 1])
373 return 0;
374
375 memprintf(&kw, "%s", args[0]);
376 for (i = 1; i <= index; i++) {
377 memprintf(&kw, "%s %s", kw, args[i]);
378 }
379
380 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
381 free(kw);
382 *err_code |= ERR_ALERT | ERR_FATAL;
383 return 1;
384}
385
386/*
387 * same as alertif_too_many_args_idx with a 0 index
388 */
389int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
390{
391 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
392}
393
Willy Tarreau620408f2016-10-21 16:37:51 +0200394/* Report a warning if a rule is placed after a 'tcp-request session' rule.
395 * Return 1 if the warning has been emitted, otherwise 0.
396 */
397int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
398{
399 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
400 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
401 file, line, arg);
402 return 1;
403 }
404 return 0;
405}
406
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200407/* Report a warning if a rule is placed after a 'tcp-request content' rule.
408 * Return 1 if the warning has been emitted, otherwise 0.
409 */
410int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
411{
412 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
413 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
414 file, line, arg);
415 return 1;
416 }
417 return 0;
418}
419
Willy Tarreau61d18892009-03-31 10:49:21 +0200420/* Report a warning if a rule is placed after a 'block' rule.
421 * Return 1 if the warning has been emitted, otherwise 0.
422 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200425 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200426 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
427 file, line, arg);
428 return 1;
429 }
430 return 0;
431}
432
Willy Tarreau5002f572014-04-23 01:32:02 +0200433/* Report a warning if a rule is placed after an 'http_request' rule.
434 * Return 1 if the warning has been emitted, otherwise 0.
435 */
436int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
437{
438 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
439 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
440 file, line, arg);
441 return 1;
442 }
443 return 0;
444}
445
Willy Tarreau61d18892009-03-31 10:49:21 +0200446/* Report a warning if a rule is placed after a reqrewrite rule.
447 * Return 1 if the warning has been emitted, otherwise 0.
448 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100449int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200450{
451 if (proxy->req_exp) {
452 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
453 file, line, arg);
454 return 1;
455 }
456 return 0;
457}
458
459/* Report a warning if a rule is placed after a reqadd rule.
460 * Return 1 if the warning has been emitted, otherwise 0.
461 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100462int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200463{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100464 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200465 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
466 file, line, arg);
467 return 1;
468 }
469 return 0;
470}
471
472/* Report a warning if a rule is placed after a redirect rule.
473 * Return 1 if the warning has been emitted, otherwise 0.
474 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
478 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
479 file, line, arg);
480 return 1;
481 }
482 return 0;
483}
484
485/* Report a warning if a rule is placed after a 'use_backend' rule.
486 * Return 1 if the warning has been emitted, otherwise 0.
487 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100488int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200489{
490 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
491 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
492 file, line, arg);
493 return 1;
494 }
495 return 0;
496}
497
Willy Tarreauee445d92014-04-23 01:39:04 +0200498/* Report a warning if a rule is placed after a 'use-server' rule.
499 * Return 1 if the warning has been emitted, otherwise 0.
500 */
501int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
502{
503 if (!LIST_ISEMPTY(&proxy->server_rules)) {
504 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
505 file, line, arg);
506 return 1;
507 }
508 return 0;
509}
510
Willy Tarreaud39ad442016-11-25 15:16:12 +0100511/* report a warning if a redirect rule is dangerously placed */
512int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200513{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100514 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200515 warnif_rule_after_use_server(proxy, file, line, arg);
516}
517
Willy Tarreaud39ad442016-11-25 15:16:12 +0100518/* report a warning if a reqadd rule is dangerously placed */
519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200520{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
522 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200523}
524
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525/* report a warning if a reqxxx rule is dangerously placed */
526int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200527{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100528 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
529 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200530}
531
532/* report a warning if an http-request rule is dangerously placed */
533int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
534{
Willy Tarreau61d18892009-03-31 10:49:21 +0200535 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100536 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200537}
538
Willy Tarreaud39ad442016-11-25 15:16:12 +0100539/* report a warning if a block rule is dangerously placed */
540int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200541{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542 return warnif_rule_after_http_req(proxy, file, line, arg) ||
543 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200544}
545
Willy Tarreaud39ad442016-11-25 15:16:12 +0100546/* report a warning if a "tcp request content" rule is dangerously placed */
547int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200548{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100549 return warnif_rule_after_block(proxy, file, line, arg) ||
550 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200551}
552
Willy Tarreaud39ad442016-11-25 15:16:12 +0100553/* report a warning if a "tcp request session" rule is dangerously placed */
554int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200555{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100556 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
557 warnif_misplaced_tcp_cont(proxy, file, line, arg);
558}
559
560/* report a warning if a "tcp request connection" rule is dangerously placed */
561int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
562{
563 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
564 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200565}
566
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100567/* Report it if a request ACL condition uses some keywords that are incompatible
568 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
569 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
570 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100571 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100572static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100573{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100574 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200575 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100576
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100577 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100578 return 0;
579
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100580 acl = acl_cond_conflicts(cond, where);
581 if (acl) {
582 if (acl->name && *acl->name)
583 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
584 file, line, acl->name, sample_ckp_names(where));
585 else
586 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 +0200587 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100588 return ERR_WARN;
589 }
590 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100591 return 0;
592
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100593 if (acl->name && *acl->name)
594 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200595 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100596 else
597 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200598 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100599 return ERR_WARN;
600}
601
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200603 * parse a line in a <global> section. Returns the error code, 0 if OK, or
604 * any combination of :
605 * - ERR_ABORT: must abort ASAP
606 * - ERR_FATAL: we can continue parsing but not start the service
607 * - ERR_WARN: a warning has been emitted
608 * - ERR_ALERT: an alert has been emitted
609 * Only the two first ones can stop processing, the two others are just
610 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200612int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613{
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200615 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616
617 if (!strcmp(args[0], "global")) { /* new section */
618 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200619 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 }
622 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200623 if (alertif_too_many_args(0, file, linenum, args, &err_code))
624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 global.mode |= MODE_DAEMON;
626 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200627 else if (!strcmp(args[0], "master-worker")) {
William Lallemand69f9b3b2017-06-01 17:38:54 +0200628 if (alertif_too_many_args(1, file, linenum, args, &err_code))
William Lallemand095ba4c2017-06-01 17:38:50 +0200629 goto out;
William Lallemand69f9b3b2017-06-01 17:38:54 +0200630 if (*args[1]) {
631 if (!strcmp(args[1], "exit-on-failure")) {
632 global.tune.options |= GTUNE_EXIT_ONFAILURE;
633 } else {
634 Alert("parsing [%s:%d] : '%s' only supports 'exit-on-failure' option.\n", file, linenum, args[0]);
635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
637 }
638 }
William Lallemand095ba4c2017-06-01 17:38:50 +0200639 global.mode |= MODE_MWORKER;
640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200642 if (alertif_too_many_args(0, file, linenum, args, &err_code))
643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 global.mode |= MODE_DEBUG;
645 }
646 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200647 if (alertif_too_many_args(0, file, linenum, args, &err_code))
648 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100649 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200651 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200652 if (alertif_too_many_args(0, file, linenum, args, &err_code))
653 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100654 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200657 if (alertif_too_many_args(0, file, linenum, args, &err_code))
658 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100659 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100661 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200662 if (alertif_too_many_args(0, file, linenum, args, &err_code))
663 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100664 global.tune.options &= ~GTUNE_USE_SPLICE;
665 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200666 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200667 if (alertif_too_many_args(0, file, linenum, args, &err_code))
668 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200669 global.tune.options &= ~GTUNE_USE_GAI;
670 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000671 else if (!strcmp(args[0], "noreuseport")) {
672 if (alertif_too_many_args(0, file, linenum, args, &err_code))
673 goto out;
674 global.tune.options &= ~GTUNE_USE_REUSEPORT;
675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200677 if (alertif_too_many_args(0, file, linenum, args, &err_code))
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 global.mode |= MODE_QUIET;
680 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200681 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200682 if (alertif_too_many_args(1, file, linenum, args, &err_code))
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 if (global.tune.maxpollevents != 0) {
685 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT;
687 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200688 }
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200693 }
694 global.tune.maxpollevents = atol(args[1]);
695 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100696 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200697 if (alertif_too_many_args(1, file, linenum, args, &err_code))
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 if (global.tune.maxaccept != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100708 }
709 global.tune.maxaccept = atol(args[1]);
710 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200711 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200712 if (alertif_too_many_args(1, file, linenum, args, &err_code))
713 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200714 if (*(args[1]) == 0) {
715 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
716 err_code |= ERR_ALERT | ERR_FATAL;
717 goto out;
718 }
719 global.tune.chksize = atol(args[1]);
720 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100721 else if (!strcmp(args[0], "tune.recv_enough")) {
722 if (alertif_too_many_args(1, file, linenum, args, &err_code))
723 goto out;
724 if (*(args[1]) == 0) {
725 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729 global.tune.recv_enough = atol(args[1]);
730 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100731 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200732 if (alertif_too_many_args(1, file, linenum, args, &err_code))
733 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739 global.tune.buf_limit = atol(args[1]);
740 if (global.tune.buf_limit) {
741 if (global.tune.buf_limit < 3)
742 global.tune.buf_limit = 3;
743 if (global.tune.buf_limit <= global.tune.reserved_bufs)
744 global.tune.buf_limit = global.tune.reserved_bufs + 1;
745 }
746 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100747 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.reserved_bufs = atol(args[1]);
756 if (global.tune.reserved_bufs < 2)
757 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100758 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
759 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100760 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200761 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
763 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +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.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200770 if (global.tune.bufsize <= 0) {
771 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100775 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100776 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200777 }
778 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200779 if (alertif_too_many_args(1, file, linenum, args, &err_code))
780 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200781 if (*(args[1]) == 0) {
782 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200787 if (global.tune.maxrewrite < 0) {
788 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
789 err_code |= ERR_ALERT | ERR_FATAL;
790 goto out;
791 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200792 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100793 else if (!strcmp(args[0], "tune.idletimer")) {
794 unsigned int idle;
795 const char *res;
796
William Lallemand1a748ae2015-05-19 16:37:23 +0200797 if (alertif_too_many_args(1, file, linenum, args, &err_code))
798 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804
805 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
806 if (res) {
807 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
808 file, linenum, *res, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812
813 if (idle > 65535) {
814 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
817 }
818 global.tune.idle_timer = idle;
819 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100820 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100823 if (global.tune.client_rcvbuf != 0) {
824 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT;
826 goto out;
827 }
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.tune.client_rcvbuf = atol(args[1]);
834 }
835 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100838 if (global.tune.server_rcvbuf != 0) {
839 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT;
841 goto out;
842 }
843 if (*(args[1]) == 0) {
844 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
848 global.tune.server_rcvbuf = atol(args[1]);
849 }
850 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200851 if (alertif_too_many_args(1, file, linenum, args, &err_code))
852 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100853 if (global.tune.client_sndbuf != 0) {
854 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
855 err_code |= ERR_ALERT;
856 goto out;
857 }
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 global.tune.client_sndbuf = atol(args[1]);
864 }
865 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200866 if (alertif_too_many_args(1, file, linenum, args, &err_code))
867 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100868 if (global.tune.server_sndbuf != 0) {
869 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT;
871 goto out;
872 }
873 if (*(args[1]) == 0) {
874 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
875 err_code |= ERR_ALERT | ERR_FATAL;
876 goto out;
877 }
878 global.tune.server_sndbuf = atol(args[1]);
879 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200880 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200881 if (alertif_too_many_args(1, file, linenum, args, &err_code))
882 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888 global.tune.pipesize = atol(args[1]);
889 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100890 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200891 if (alertif_too_many_args(1, file, linenum, args, &err_code))
892 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
898 global.tune.cookie_len = atol(args[1]) + 1;
899 }
Stéphane Cottin23e9e932017-05-18 08:58:41 +0200900 else if (!strcmp(args[0], "tune.http.logurilen")) {
901 if (alertif_too_many_args(1, file, linenum, args, &err_code))
902 goto out;
903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908 global.tune.requri_len = atol(args[1]) + 1;
909 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200910 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200911 if (alertif_too_many_args(1, file, linenum, args, &err_code))
912 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200913 if (*(args[1]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918 global.tune.max_http_hdr = atol(args[1]);
919 }
William Lallemandf3747832012-11-09 12:33:10 +0100920 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200921 if (alertif_too_many_args(1, file, linenum, args, &err_code))
922 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100923 if (*args[1]) {
924 global.tune.comp_maxlevel = atoi(args[1]);
925 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
926 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
927 file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 } else {
932 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
933 file, linenum, args[0]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200938 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
939 if (*args[1]) {
940 global.tune.pattern_cache = atoi(args[1]);
941 if (global.tune.pattern_cache < 0) {
942 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
943 file, linenum, args[0]);
944 err_code |= ERR_ALERT | ERR_FATAL;
945 goto out;
946 }
947 } else {
948 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
949 file, linenum, args[0]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200955 if (alertif_too_many_args(1, file, linenum, args, &err_code))
956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200958 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200959 err_code |= ERR_ALERT;
960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 }
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100967 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
968 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]);
969 err_code |= ERR_WARN;
970 goto out;
971 }
972
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200975 if (alertif_too_many_args(1, file, linenum, args, &err_code))
976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200978 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200979 err_code |= ERR_ALERT;
980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 }
982 if (*(args[1]) == 0) {
983 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100987 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
988 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]);
989 err_code |= ERR_WARN;
990 goto out;
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 }
Simon Horman98637e52014-06-20 12:30:16 +0900993 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200994 if (alertif_too_many_args(0, file, linenum, args, &err_code))
995 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900996 global.external_check = 1;
997 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200998 /* user/group name handling */
999 else if (!strcmp(args[0], "user")) {
1000 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001001 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1002 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001003 if (global.uid != 0) {
1004 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT;
1006 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001007 }
1008 errno = 0;
1009 ha_user = getpwnam(args[1]);
1010 if (ha_user != NULL) {
1011 global.uid = (int)ha_user->pw_uid;
1012 }
1013 else {
1014 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 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001016 }
1017 }
1018 else if (!strcmp(args[0], "group")) {
1019 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1021 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001022 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001023 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001024 err_code |= ERR_ALERT;
1025 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001026 }
1027 errno = 0;
1028 ha_group = getgrnam(args[1]);
1029 if (ha_group != NULL) {
1030 global.gid = (int)ha_group->gr_gid;
1031 }
1032 else {
1033 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 +02001034 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001035 }
1036 }
1037 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001039 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 if (*(args[1]) == 0) {
1042 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 }
1046 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001047 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1048 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1049 file, linenum, args[0], LONGBITS, global.nbproc);
1050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
1052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 }
1054 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001055 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 if (global.maxconn != 0) {
1058 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001059 err_code |= ERR_ALERT;
1060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 }
1062 if (*(args[1]) == 0) {
1063 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066 }
1067 global.maxconn = atol(args[1]);
1068#ifdef SYSTEM_MAXCONN
1069 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1070 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);
1071 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001072 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074#endif /* SYSTEM_MAXCONN */
1075 }
Emeric Brun850efd52014-01-29 12:24:34 +01001076 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001077 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1078 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001079 if (*(args[1]) == 0) {
1080 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 if (strcmp(args[1],"none") == 0)
1085 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1086 else if (strcmp(args[1],"required") == 0)
1087 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1088 else {
1089 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
1092 }
1093 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001094 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001095 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1096 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001097 if (global.cps_lim != 0) {
1098 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1099 err_code |= ERR_ALERT;
1100 goto out;
1101 }
1102 if (*(args[1]) == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
1107 global.cps_lim = atol(args[1]);
1108 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001109 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001110 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1111 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001112 if (global.sps_lim != 0) {
1113 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT;
1115 goto out;
1116 }
1117 if (*(args[1]) == 0) {
1118 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto out;
1121 }
1122 global.sps_lim = atol(args[1]);
1123 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001124 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001125 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1126 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001127 if (global.ssl_lim != 0) {
1128 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1129 err_code |= ERR_ALERT;
1130 goto out;
1131 }
1132 if (*(args[1]) == 0) {
1133 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto out;
1136 }
1137 global.ssl_lim = atol(args[1]);
1138 }
William Lallemandd85f9172012-11-09 17:05:39 +01001139 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001140 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1141 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001142 if (*(args[1]) == 0) {
1143 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1144 err_code |= ERR_ALERT | ERR_FATAL;
1145 goto out;
1146 }
1147 global.comp_rate_lim = atoi(args[1]) * 1024;
1148 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001149 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001150 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1151 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001152 if (global.maxpipes != 0) {
1153 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT;
1155 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001156 }
1157 if (*(args[1]) == 0) {
1158 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001161 }
1162 global.maxpipes = atol(args[1]);
1163 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001164 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001165 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1166 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001167 if (*(args[1]) == 0) {
1168 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto out;
1171 }
William Lallemande3a7d992012-11-20 11:25:20 +01001172 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001173 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001174 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001175 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1176 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001177 if (*(args[1]) == 0) {
1178 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1179 err_code |= ERR_ALERT | ERR_FATAL;
1180 goto out;
1181 }
1182 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001183 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001184 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto out;
1187 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001188 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001189
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001191 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 if (global.rlimit_nofile != 0) {
1194 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001195 err_code |= ERR_ALERT;
1196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 }
1198 if (*(args[1]) == 0) {
1199 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203 global.rlimit_nofile = atol(args[1]);
1204 }
1205 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001206 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 if (global.chroot != NULL) {
1209 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001210 err_code |= ERR_ALERT;
1211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001212 }
1213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 global.chroot = strdup(args[1]);
1219 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001220 else if (!strcmp(args[0], "description")) {
1221 int i, len=0;
1222 char *d;
1223
1224 if (!*args[1]) {
1225 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1226 file, linenum, args[0]);
1227 err_code |= ERR_ALERT | ERR_FATAL;
1228 goto out;
1229 }
1230
Willy Tarreau348acfe2014-04-14 15:00:39 +02001231 for (i = 1; *args[i]; i++)
1232 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001233
1234 if (global.desc)
1235 free(global.desc);
1236
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001237 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001238
Willy Tarreau348acfe2014-04-14 15:00:39 +02001239 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1240 for (i = 2; *args[i]; i++)
1241 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001242 }
1243 else if (!strcmp(args[0], "node")) {
1244 int i;
1245 char c;
1246
William Lallemand1a748ae2015-05-19 16:37:23 +02001247 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1248 goto out;
1249
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001250 for (i=0; args[1][i]; i++) {
1251 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001252 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1253 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001254 break;
1255 }
1256
1257 if (!i || args[1][i]) {
1258 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1259 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1260 file, linenum, args[0]);
1261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
1263 }
1264
1265 if (global.node)
1266 free(global.node);
1267
1268 global.node = strdup(args[1]);
1269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001271 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 if (global.pidfile != NULL) {
1274 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001275 err_code |= ERR_ALERT;
1276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 }
1278 if (*(args[1]) == 0) {
1279 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282 }
1283 global.pidfile = strdup(args[1]);
1284 }
Emeric Bruned760922010-10-22 17:59:25 +02001285 else if (!strcmp(args[0], "unix-bind")) {
1286 int cur_arg = 1;
1287 while (*(args[cur_arg])) {
1288 if (!strcmp(args[cur_arg], "prefix")) {
1289 if (global.unix_bind.prefix != NULL) {
1290 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1291 err_code |= ERR_ALERT;
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (*(args[cur_arg+1]) == 0) {
1297 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1302 cur_arg += 2;
1303 continue;
1304 }
1305
1306 if (!strcmp(args[cur_arg], "mode")) {
1307
1308 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1309 cur_arg += 2;
1310 continue;
1311 }
1312
1313 if (!strcmp(args[cur_arg], "uid")) {
1314
1315 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1316 cur_arg += 2;
1317 continue;
1318 }
1319
1320 if (!strcmp(args[cur_arg], "gid")) {
1321
1322 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1323 cur_arg += 2;
1324 continue;
1325 }
1326
1327 if (!strcmp(args[cur_arg], "user")) {
1328 struct passwd *user;
1329
1330 user = getpwnam(args[cur_arg + 1]);
1331 if (!user) {
1332 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1333 file, linenum, args[0], args[cur_arg + 1 ]);
1334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
1336 }
1337
1338 global.unix_bind.ux.uid = user->pw_uid;
1339 cur_arg += 2;
1340 continue;
1341 }
1342
1343 if (!strcmp(args[cur_arg], "group")) {
1344 struct group *group;
1345
1346 group = getgrnam(args[cur_arg + 1]);
1347 if (!group) {
1348 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1349 file, linenum, args[0], args[cur_arg + 1 ]);
1350 err_code |= ERR_ALERT | ERR_FATAL;
1351 goto out;
1352 }
1353
1354 global.unix_bind.ux.gid = group->gr_gid;
1355 cur_arg += 2;
1356 continue;
1357 }
1358
Willy Tarreaub48f9582011-09-05 01:17:06 +02001359 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001360 file, linenum, args[0]);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363 }
1364 }
William Lallemand0f99e342011-10-12 17:50:54 +02001365 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1366 /* delete previous herited or defined syslog servers */
1367 struct logsrv *back;
1368 struct logsrv *tmp;
1369
1370 if (*(args[1]) != 0) {
1371 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto out;
1374 }
1375
1376 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1377 LIST_DEL(&tmp->list);
1378 free(tmp);
1379 }
1380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001382 struct sockaddr_storage *sk;
1383 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001384 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001385 int arg = 0;
1386 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001387
William Lallemand1a748ae2015-05-19 16:37:23 +02001388 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1389 goto out;
1390
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 if (*(args[1]) == 0 || *(args[2]) == 0) {
1392 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 }
William Lallemand0f99e342011-10-12 17:50:54 +02001396
Vincent Bernat02779b62016-04-03 13:48:43 +02001397 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001398
Willy Tarreau18324f52014-06-27 18:10:07 +02001399 /* just after the address, a length may be specified */
1400 if (strcmp(args[arg+2], "len") == 0) {
1401 len = atoi(args[arg+3]);
1402 if (len < 80 || len > 65535) {
1403 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1404 file, linenum, args[arg+3]);
1405 err_code |= ERR_ALERT | ERR_FATAL;
1406 goto out;
1407 }
1408 logsrv->maxlen = len;
1409
1410 /* skip these two args */
1411 arg += 2;
1412 }
1413 else
1414 logsrv->maxlen = MAX_SYSLOG_LEN;
1415
1416 if (logsrv->maxlen > global.max_syslog_len) {
1417 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001418 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1419 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1420 logline = my_realloc2(logline, global.max_syslog_len + 1);
1421 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001422 }
1423
Dragan Dosen1322d092015-09-22 16:05:32 +02001424 /* after the length, a format may be specified */
1425 if (strcmp(args[arg+2], "format") == 0) {
1426 logsrv->format = get_log_format(args[arg+3]);
1427 if (logsrv->format < 0) {
1428 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1429 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001430 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001431 goto out;
1432 }
1433
1434 /* skip these two args */
1435 arg += 2;
1436 }
1437
David Carlier97880bb2016-04-08 10:35:26 +01001438 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1439 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001440 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001441 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001442
Willy Tarreau18324f52014-06-27 18:10:07 +02001443 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001444 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001445 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001447 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
1449
William Lallemand0f99e342011-10-12 17:50:54 +02001450 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001451 if (*(args[arg+3])) {
1452 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001453 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001454 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001455 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001456 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 }
1458 }
1459
William Lallemand0f99e342011-10-12 17:50:54 +02001460 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001461 if (*(args[arg+4])) {
1462 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001463 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001464 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001465 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001466 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001467 }
1468 }
1469
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001470 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001471 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001472 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001473 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001474 free(logsrv);
1475 goto out;
1476 }
1477 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001478
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001479 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001480 if (port1 != port2) {
1481 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1482 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001483 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001484 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001485 goto out;
1486 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001487
William Lallemand0f99e342011-10-12 17:50:54 +02001488 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001489 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001490 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492
William Lallemand0f99e342011-10-12 17:50:54 +02001493 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001494 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001495 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1496 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001497
1498 if (global.log_send_hostname != NULL) {
1499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1500 err_code |= ERR_ALERT;
1501 goto out;
1502 }
1503
1504 if (*(args[1]))
1505 name = args[1];
1506 else
1507 name = hostname;
1508
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001509 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001510 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001511 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001512 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1513 if (global.server_state_base != NULL) {
1514 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1515 err_code |= ERR_ALERT;
1516 goto out;
1517 }
1518
1519 if (!*(args[1])) {
1520 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1521 err_code |= ERR_FATAL;
1522 goto out;
1523 }
1524
1525 global.server_state_base = strdup(args[1]);
1526 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001527 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1528 if (global.server_state_file != NULL) {
1529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1530 err_code |= ERR_ALERT;
1531 goto out;
1532 }
1533
1534 if (!*(args[1])) {
1535 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1536 err_code |= ERR_FATAL;
1537 goto out;
1538 }
1539
1540 global.server_state_file = strdup(args[1]);
1541 }
Kevinm48936af2010-12-22 16:08:21 +00001542 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001543 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1544 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001545 if (*(args[1]) == 0) {
1546 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1547 err_code |= ERR_ALERT | ERR_FATAL;
1548 goto out;
1549 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001550 chunk_destroy(&global.log_tag);
1551 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001552 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001553 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001554 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1555 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001556 if (global.spread_checks != 0) {
1557 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001558 err_code |= ERR_ALERT;
1559 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001560 }
1561 if (*(args[1]) == 0) {
1562 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001563 err_code |= ERR_ALERT | ERR_FATAL;
1564 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001565 }
1566 global.spread_checks = atol(args[1]);
1567 if (global.spread_checks < 0 || global.spread_checks > 50) {
1568 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001572 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1573 const char *err;
1574 unsigned int val;
1575
William Lallemand1a748ae2015-05-19 16:37:23 +02001576 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1577 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001578 if (*(args[1]) == 0) {
1579 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
1583
1584 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1585 if (err) {
1586 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1587 err_code |= ERR_ALERT | ERR_FATAL;
1588 }
1589 global.max_spread_checks = val;
1590 if (global.max_spread_checks < 0) {
1591 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1592 err_code |= ERR_ALERT | ERR_FATAL;
1593 }
1594 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001595 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1596#ifdef USE_CPU_AFFINITY
1597 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001598 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001599 unsigned long cpus = 0;
1600
1601 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001602 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001603 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001604 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001605 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001606 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001607 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001608 proc = atol(args[1]);
1609 if (proc >= 1 && proc <= LONGBITS)
1610 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001611 }
1612
1613 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001614 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",
1615 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
1618 }
1619
1620 cur_arg = 2;
1621 while (*args[cur_arg]) {
1622 unsigned int low, high;
1623
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001624 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001625 char *dash = strchr(args[cur_arg], '-');
1626
1627 low = high = str2uic(args[cur_arg]);
1628 if (dash)
1629 high = str2uic(dash + 1);
1630
1631 if (high < low) {
1632 unsigned int swap = low;
1633 low = high;
1634 high = swap;
1635 }
1636
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001637 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001638 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001639 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001640 err_code |= ERR_ALERT | ERR_FATAL;
1641 goto out;
1642 }
1643
1644 while (low <= high)
1645 cpus |= 1UL << low++;
1646 }
1647 else {
1648 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1649 file, linenum, args[0], args[cur_arg]);
1650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653 cur_arg++;
1654 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001655 for (i = 0; i < LONGBITS; i++)
1656 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001657 global.cpu_map[i] = cpus;
1658#else
1659 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662#endif
1663 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001664 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1665 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1666 goto out;
1667
1668 if (*(args[2]) == 0) {
1669 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
1672 }
1673
1674 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1675 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1676 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
1679 }
1680 }
1681 else if (!strcmp(args[0], "unsetenv")) {
1682 int arg;
1683
1684 if (*(args[1]) == 0) {
1685 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
1688 }
1689
1690 for (arg = 1; *args[arg]; arg++) {
1691 if (unsetenv(args[arg]) != 0) {
1692 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696 }
1697 }
1698 else if (!strcmp(args[0], "resetenv")) {
1699 extern char **environ;
1700 char **env = environ;
1701
1702 /* args contain variable names to keep, one per argument */
1703 while (*env) {
1704 int arg;
1705
1706 /* look for current variable in among all those we want to keep */
1707 for (arg = 1; *args[arg]; arg++) {
1708 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1709 (*env)[strlen(args[arg])] == '=')
1710 break;
1711 }
1712
1713 /* delete this variable */
1714 if (!*args[arg]) {
1715 char *delim = strchr(*env, '=');
1716
1717 if (!delim || delim - *env >= trash.size) {
1718 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
1721 }
1722
1723 memcpy(trash.str, *env, delim - *env);
1724 trash.str[delim - *env] = 0;
1725
1726 if (unsetenv(trash.str) != 0) {
1727 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
1731 }
1732 else
1733 env++;
1734 }
1735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001737 struct cfg_kw_list *kwl;
1738 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001739 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001740
1741 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1742 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1743 if (kwl->kw[index].section != CFG_GLOBAL)
1744 continue;
1745 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001746 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001747 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001748 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001749 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001750 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001751 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001752 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001753 err_code |= ERR_WARN;
1754 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001755 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001756 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001757 }
1758 }
1759 }
1760
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001762 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001764
Willy Tarreau058e9072009-07-20 09:30:05 +02001765 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001766 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001767 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768}
1769
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001770void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001772 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 defproxy.mode = PR_MODE_TCP;
1774 defproxy.state = PR_STNEW;
1775 defproxy.maxconn = cfg_maxpconn;
1776 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001777 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001778 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001779
Simon Horman66183002013-02-23 10:16:43 +09001780 defproxy.defsrv.check.inter = DEF_CHKINTR;
1781 defproxy.defsrv.check.fastinter = 0;
1782 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001783 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1784 defproxy.defsrv.agent.fastinter = 0;
1785 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001786 defproxy.defsrv.check.rise = DEF_RISETIME;
1787 defproxy.defsrv.check.fall = DEF_FALLTIME;
1788 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1789 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001790 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001791 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001792 defproxy.defsrv.maxqueue = 0;
1793 defproxy.defsrv.minconn = 0;
1794 defproxy.defsrv.maxconn = 0;
1795 defproxy.defsrv.slowstart = 0;
1796 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1797 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1798 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001799
1800 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001801 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802}
1803
Willy Tarreauade5ec42010-01-28 19:33:49 +01001804
Willy Tarreau63af98d2014-05-18 08:11:41 +02001805/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1806 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1807 * ERR_FATAL in case of error.
1808 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001809static int create_cond_regex_rule(const char *file, int line,
1810 struct proxy *px, int dir, int action, int flags,
1811 const char *cmd, const char *reg, const char *repl,
1812 const char **cond_start)
1813{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001814 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001815 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001816 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001817 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001818 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001819 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001820 int cs;
1821 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001822
1823 if (px == &defproxy) {
1824 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001825 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001826 goto err;
1827 }
1828
1829 if (*reg == 0) {
1830 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001831 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001832 goto err;
1833 }
1834
Christopher Faulet898566e2016-10-26 11:06:28 +02001835 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001836 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001837
Willy Tarreau5321c422010-01-28 20:35:13 +01001838 if (cond_start &&
1839 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001840 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1841 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1842 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001843 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001844 goto err;
1845 }
1846 }
1847 else if (cond_start && **cond_start) {
1848 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1849 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001851 goto err;
1852 }
1853
Willy Tarreau63af98d2014-05-18 08:11:41 +02001854 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001855 (dir == SMP_OPT_DIR_REQ) ?
1856 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1857 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1858 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001859
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001860 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001861 if (!preg) {
1862 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001864 goto err;
1865 }
1866
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001867 cs = !(flags & REG_ICASE);
1868 cap = !(flags & REG_NOSUB);
1869 error = NULL;
1870 if (!regex_comp(reg, preg, cs, cap, &error)) {
1871 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1872 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001873 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001874 goto err;
1875 }
1876
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001877 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001878 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001879 if (repl && err) {
1880 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1881 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001882 ret_code |= ERR_ALERT | ERR_FATAL;
1883 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001884 }
1885
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001886 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887 ret_code |= ERR_WARN;
1888
1889 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001890
Willy Tarreau63af98d2014-05-18 08:11:41 +02001891 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001892 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001893 err:
1894 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001895 free(errmsg);
1896 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001897}
1898
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899/*
William Lallemand51097192015-04-14 16:35:22 +02001900 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001901 * Returns the error code, 0 if OK, or any combination of :
1902 * - ERR_ABORT: must abort ASAP
1903 * - ERR_FATAL: we can continue parsing but not start the service
1904 * - ERR_WARN: a warning has been emitted
1905 * - ERR_ALERT: an alert has been emitted
1906 * Only the two first ones can stop processing, the two others are just
1907 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001909int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1910{
1911 static struct peers *curpeers = NULL;
1912 struct peer *newpeer = NULL;
1913 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001914 struct bind_conf *bind_conf;
1915 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001916 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001917 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001918
1919 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001920 if (!*args[1]) {
1921 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001922 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001923 goto out;
1924 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001925
William Lallemand6e62fb62015-04-28 16:55:23 +02001926 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1927 goto out;
1928
Emeric Brun32da3c42010-09-23 18:39:19 +02001929 err = invalid_char(args[1]);
1930 if (err) {
1931 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1932 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001933 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001934 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001935 }
1936
1937 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1938 /*
1939 * If there are two proxies with the same name only following
1940 * combinations are allowed:
1941 */
1942 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001943 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 +02001944 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001945 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001946 }
1947 }
1948
Vincent Bernat02779b62016-04-03 13:48:43 +02001949 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001950 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1951 err_code |= ERR_ALERT | ERR_ABORT;
1952 goto out;
1953 }
1954
1955 curpeers->next = peers;
1956 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001957 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001958 curpeers->conf.line = linenum;
1959 curpeers->last_change = now.tv_sec;
1960 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001961 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001962 }
1963 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001964 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001965 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001966 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001967
1968 if (!*args[2]) {
1969 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1970 file, linenum, args[0]);
1971 err_code |= ERR_ALERT | ERR_FATAL;
1972 goto out;
1973 }
1974
1975 err = invalid_char(args[1]);
1976 if (err) {
1977 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1978 file, linenum, *err, args[1]);
1979 err_code |= ERR_ALERT | ERR_FATAL;
1980 goto out;
1981 }
1982
Vincent Bernat02779b62016-04-03 13:48:43 +02001983 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001984 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1985 err_code |= ERR_ALERT | ERR_ABORT;
1986 goto out;
1987 }
1988
1989 /* the peers are linked backwards first */
1990 curpeers->count++;
1991 newpeer->next = curpeers->remote;
1992 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001993 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001994 newpeer->conf.line = linenum;
1995
1996 newpeer->last_change = now.tv_sec;
1997 newpeer->id = strdup(args[1]);
1998
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001999 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002000 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002001 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002004 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002005
2006 proto = protocol_by_family(sk->ss_family);
2007 if (!proto || !proto->connect) {
2008 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2009 file, linenum, args[0], args[1]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002013
2014 if (port1 != port2) {
2015 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2016 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
2019 }
2020
Willy Tarreau2aa38802013-02-20 19:20:59 +01002021 if (!port1) {
2022 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2023 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002027
Emeric Brun32da3c42010-09-23 18:39:19 +02002028 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002029 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002030 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002031 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002032
Emeric Brun32da3c42010-09-23 18:39:19 +02002033 if (strcmp(newpeer->id, localpeer) == 0) {
2034 /* Current is local peer, it define a frontend */
2035 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002036 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002037
2038 if (!curpeers->peers_fe) {
2039 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2041 err_code |= ERR_ALERT | ERR_ABORT;
2042 goto out;
2043 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002044
Willy Tarreau237250c2011-07-29 01:49:03 +02002045 init_new_proxy(curpeers->peers_fe);
2046 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002047 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002048 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2049 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002050 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002051
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002052 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002053
Willy Tarreau902636f2013-03-10 19:44:48 +01002054 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2055 if (errmsg && *errmsg) {
2056 indent_msg(&errmsg, 2);
2057 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002058 }
2059 else
2060 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2061 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002062 err_code |= ERR_FATAL;
2063 goto out;
2064 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002065
2066 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002067 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002068 l->maxconn = curpeers->peers_fe->maxconn;
2069 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002070 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002071 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002072 l->analysers |= curpeers->peers_fe->fe_req_ana;
2073 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002074 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2075 global.maxsock += l->maxconn;
2076 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002077 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002078 else {
2079 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2080 file, linenum, args[0], args[1],
2081 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2082 err_code |= ERR_FATAL;
2083 goto out;
2084 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002085 }
2086 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002087 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2088 curpeers->state = PR_STSTOPPED;
2089 }
2090 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2091 curpeers->state = PR_STNEW;
2092 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002093 else if (*args[0] != 0) {
2094 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
2097 }
2098
2099out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002100 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002101 return err_code;
2102}
2103
Baptiste Assmann325137d2015-04-13 23:40:55 +02002104/*
2105 * Parse a <resolvers> section.
2106 * Returns the error code, 0 if OK, or any combination of :
2107 * - ERR_ABORT: must abort ASAP
2108 * - ERR_FATAL: we can continue parsing but not start the service
2109 * - ERR_WARN: a warning has been emitted
2110 * - ERR_ALERT: an alert has been emitted
2111 * Only the two first ones can stop processing, the two others are just
2112 * indicators.
2113 */
2114int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2115{
2116 static struct dns_resolvers *curr_resolvers = NULL;
2117 struct dns_nameserver *newnameserver = NULL;
2118 const char *err;
2119 int err_code = 0;
2120 char *errmsg = NULL;
2121
2122 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2123 if (!*args[1]) {
2124 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2125 err_code |= ERR_ALERT | ERR_ABORT;
2126 goto out;
2127 }
2128
2129 err = invalid_char(args[1]);
2130 if (err) {
2131 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2132 file, linenum, *err, args[0], args[1]);
2133 err_code |= ERR_ALERT | ERR_ABORT;
2134 goto out;
2135 }
2136
2137 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2138 /* Error if two resolvers owns the same name */
2139 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2140 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2141 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2142 err_code |= ERR_ALERT | ERR_ABORT;
2143 }
2144 }
2145
Vincent Bernat02779b62016-04-03 13:48:43 +02002146 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002147 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2148 err_code |= ERR_ALERT | ERR_ABORT;
2149 goto out;
2150 }
2151
2152 /* default values */
2153 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2154 curr_resolvers->conf.file = strdup(file);
2155 curr_resolvers->conf.line = linenum;
2156 curr_resolvers->id = strdup(args[1]);
2157 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002158 /* default hold period for nx, other, refuse and timeout is 30s */
2159 curr_resolvers->hold.nx = 30000;
2160 curr_resolvers->hold.other = 30000;
2161 curr_resolvers->hold.refused = 30000;
2162 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002163 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002164 curr_resolvers->hold.valid = 10000;
2165 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002166 curr_resolvers->resolve_retries = 3;
2167 LIST_INIT(&curr_resolvers->nameserver_list);
2168 LIST_INIT(&curr_resolvers->curr_resolution);
2169 }
2170 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2171 struct sockaddr_storage *sk;
2172 int port1, port2;
2173 struct protocol *proto;
2174
2175 if (!*args[2]) {
2176 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2177 file, linenum, args[0]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181
2182 err = invalid_char(args[1]);
2183 if (err) {
2184 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2185 file, linenum, *err, args[1]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189
Baptiste Assmanna315c552015-11-02 22:55:49 +01002190 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2191 /* Error if two resolvers owns the same name */
2192 if (strcmp(newnameserver->id, args[1]) == 0) {
2193 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2194 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2195 err_code |= ERR_ALERT | ERR_FATAL;
2196 }
2197 }
2198
Vincent Bernat02779b62016-04-03 13:48:43 +02002199 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002200 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2201 err_code |= ERR_ALERT | ERR_ABORT;
2202 goto out;
2203 }
2204
2205 /* the nameservers are linked backward first */
2206 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2207 curr_resolvers->count_nameservers++;
2208 newnameserver->resolvers = curr_resolvers;
2209 newnameserver->conf.file = strdup(file);
2210 newnameserver->conf.line = linenum;
2211 newnameserver->id = strdup(args[1]);
2212
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002213 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002214 if (!sk) {
2215 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
2218 }
2219
2220 proto = protocol_by_family(sk->ss_family);
2221 if (!proto || !proto->connect) {
2222 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2223 file, linenum, args[0], args[1]);
2224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
2226 }
2227
2228 if (port1 != port2) {
2229 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2230 file, linenum, args[0], args[1], args[2]);
2231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
2233 }
2234
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002235 if (!port1 && !port2) {
2236 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2237 file, linenum, args[0], args[1]);
2238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
2240 }
2241
Baptiste Assmann325137d2015-04-13 23:40:55 +02002242 newnameserver->addr = *sk;
2243 }
2244 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2245 const char *res;
2246 unsigned int time;
2247
2248 if (!*args[2]) {
2249 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2250 file, linenum, args[0]);
2251 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
2254 }
2255 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2256 if (res) {
2257 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2258 file, linenum, *res, args[0]);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002262 if (strcmp(args[1], "nx") == 0)
2263 curr_resolvers->hold.nx = time;
2264 else if (strcmp(args[1], "other") == 0)
2265 curr_resolvers->hold.other = time;
2266 else if (strcmp(args[1], "refused") == 0)
2267 curr_resolvers->hold.refused = time;
2268 else if (strcmp(args[1], "timeout") == 0)
2269 curr_resolvers->hold.timeout = time;
2270 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002271 curr_resolvers->hold.valid = time;
2272 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002273 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2274 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
2277 }
2278
2279 }
2280 else if (strcmp(args[0], "resolve_retries") == 0) {
2281 if (!*args[1]) {
2282 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2283 file, linenum, args[0]);
2284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
2286 }
2287 curr_resolvers->resolve_retries = atoi(args[1]);
2288 }
2289 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002290 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002291 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2292 file, linenum, args[0]);
2293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
2295 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002296 else if (strcmp(args[1], "retry") == 0) {
2297 const char *res;
2298 unsigned int timeout_retry;
2299
2300 if (!*args[2]) {
2301 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2302 file, linenum, args[0], args[1]);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2307 if (res) {
2308 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2309 file, linenum, *res, args[0], args[1]);
2310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
2312 }
2313 curr_resolvers->timeout.retry = timeout_retry;
2314 }
2315 else {
2316 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2317 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002321 } /* neither "nameserver" nor "resolvers" */
2322 else if (*args[0] != 0) {
2323 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
2326 }
2327
2328 out:
2329 free(errmsg);
2330 return err_code;
2331}
Simon Horman0d16a402015-01-30 11:22:58 +09002332
2333/*
William Lallemand51097192015-04-14 16:35:22 +02002334 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002335 * Returns the error code, 0 if OK, or any combination of :
2336 * - ERR_ABORT: must abort ASAP
2337 * - ERR_FATAL: we can continue parsing but not start the service
2338 * - ERR_WARN: a warning has been emitted
2339 * - ERR_ALERT: an alert has been emitted
2340 * Only the two first ones can stop processing, the two others are just
2341 * indicators.
2342 */
2343int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2344{
2345 static struct mailers *curmailers = NULL;
2346 struct mailer *newmailer = NULL;
2347 const char *err;
2348 int err_code = 0;
2349 char *errmsg = NULL;
2350
2351 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2352 if (!*args[1]) {
2353 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2354 err_code |= ERR_ALERT | ERR_ABORT;
2355 goto out;
2356 }
2357
2358 err = invalid_char(args[1]);
2359 if (err) {
2360 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2361 file, linenum, *err, args[0], args[1]);
2362 err_code |= ERR_ALERT | ERR_ABORT;
2363 goto out;
2364 }
2365
2366 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2367 /*
2368 * If there are two proxies with the same name only following
2369 * combinations are allowed:
2370 */
2371 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002372 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 +09002373 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002375 }
2376 }
2377
Vincent Bernat02779b62016-04-03 13:48:43 +02002378 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2380 err_code |= ERR_ALERT | ERR_ABORT;
2381 goto out;
2382 }
2383
2384 curmailers->next = mailers;
2385 mailers = curmailers;
2386 curmailers->conf.file = strdup(file);
2387 curmailers->conf.line = linenum;
2388 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002389 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2390 * But need enough time so that timeouts don't occur
2391 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002392 }
2393 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2394 struct sockaddr_storage *sk;
2395 int port1, port2;
2396 struct protocol *proto;
2397
2398 if (!*args[2]) {
2399 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2400 file, linenum, args[0]);
2401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
2403 }
2404
2405 err = invalid_char(args[1]);
2406 if (err) {
2407 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2408 file, linenum, *err, args[1]);
2409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
2411 }
2412
Vincent Bernat02779b62016-04-03 13:48:43 +02002413 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002414 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2415 err_code |= ERR_ALERT | ERR_ABORT;
2416 goto out;
2417 }
2418
2419 /* the mailers are linked backwards first */
2420 curmailers->count++;
2421 newmailer->next = curmailers->mailer_list;
2422 curmailers->mailer_list = newmailer;
2423 newmailer->mailers = curmailers;
2424 newmailer->conf.file = strdup(file);
2425 newmailer->conf.line = linenum;
2426
2427 newmailer->id = strdup(args[1]);
2428
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002429 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002430 if (!sk) {
2431 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435
2436 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002437 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2438 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002439 file, linenum, args[0], args[1]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
2444 if (port1 != port2) {
2445 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2446 file, linenum, args[0], args[1], args[2]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
2451 if (!port1) {
2452 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2453 file, linenum, args[0], args[1], args[2]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
2458 newmailer->addr = *sk;
2459 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002460 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002461 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002462 }
2463 else if (strcmp(args[0], "timeout") == 0) {
2464 if (!*args[1]) {
2465 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2466 file, linenum, args[0]);
2467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
2469 }
2470 else if (strcmp(args[1], "mail") == 0) {
2471 const char *res;
2472 unsigned int timeout_mail;
2473 if (!*args[2]) {
2474 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2475 file, linenum, args[0], args[1]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2480 if (res) {
2481 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2482 file, linenum, *res, args[0]);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486 if (timeout_mail <= 0) {
2487 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491 curmailers->timeout.mail = timeout_mail;
2492 } else {
2493 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2494 file, linenum, args[0], args[1]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498 }
Simon Horman0d16a402015-01-30 11:22:58 +09002499 else if (*args[0] != 0) {
2500 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
2504
2505out:
2506 free(errmsg);
2507 return err_code;
2508}
2509
Simon Horman9dc49962015-01-30 11:22:59 +09002510static void free_email_alert(struct proxy *p)
2511{
2512 free(p->email_alert.mailers.name);
2513 p->email_alert.mailers.name = NULL;
2514 free(p->email_alert.from);
2515 p->email_alert.from = NULL;
2516 free(p->email_alert.to);
2517 p->email_alert.to = NULL;
2518 free(p->email_alert.myhostname);
2519 p->email_alert.myhostname = NULL;
2520}
2521
Willy Tarreau3842f002009-06-14 11:39:52 +02002522int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523{
2524 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002525 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002526 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002527 int rc;
2528 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002529 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002530 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002531 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002532 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002533 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534
Willy Tarreau977b8e42006-12-29 14:19:17 +01002535 if (!strcmp(args[0], "listen"))
2536 rc = PR_CAP_LISTEN;
2537 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002538 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002539 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002540 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002541 else
2542 rc = PR_CAP_NONE;
2543
2544 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 if (!*args[1]) {
2546 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002547 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_ABORT;
2550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002552
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002553 err = invalid_char(args[1]);
2554 if (err) {
2555 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2556 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002558 }
2559
Willy Tarreau8f50b682015-05-26 11:45:02 +02002560 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2561 if (curproxy) {
2562 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2563 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2564 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002566 }
2567
Vincent Bernat02779b62016-04-03 13:48:43 +02002568 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_ABORT;
2571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002573
Willy Tarreau97cb7802010-01-03 20:23:58 +01002574 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 curproxy->next = proxy;
2576 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002577 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2578 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002579 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002582 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583
William Lallemand6e62fb62015-04-28 16:55:23 +02002584 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2585 if (curproxy->cap & PR_CAP_FE)
2586 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
2589
2590 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002591 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002592 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002593
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002596 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002597 curproxy->no_options = defproxy.no_options;
2598 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002599 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002600 curproxy->except_net = defproxy.except_net;
2601 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002602 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002603 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002605 if (defproxy.fwdfor_hdr_len) {
2606 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2607 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2608 }
2609
Willy Tarreaub86db342009-11-30 11:50:16 +01002610 if (defproxy.orgto_hdr_len) {
2611 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2612 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2613 }
2614
Mark Lamourinec2247f02012-01-04 13:02:01 -05002615 if (defproxy.server_id_hdr_len) {
2616 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2617 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2618 }
2619
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620 if (curproxy->cap & PR_CAP_FE) {
2621 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002622 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002623 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002624
2625 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002626 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2627 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002628
2629 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631
Willy Tarreau977b8e42006-12-29 14:19:17 +01002632 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002633 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002634 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002635 curproxy->fullconn = defproxy.fullconn;
2636 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002637 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002638 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002640 if (defproxy.check_req) {
2641 curproxy->check_req = calloc(1, defproxy.check_len);
2642 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2643 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002644 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002646 if (defproxy.expect_str) {
2647 curproxy->expect_str = strdup(defproxy.expect_str);
2648 if (defproxy.expect_regex) {
2649 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002650 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2651 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002652 }
2653 }
2654
Willy Tarreau67402132012-05-31 20:40:20 +02002655 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002656 if (defproxy.cookie_name)
2657 curproxy->cookie_name = strdup(defproxy.cookie_name);
2658 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002659
2660 if (defproxy.dyncookie_key)
2661 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002662 if (defproxy.cookie_domain)
2663 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002664
Willy Tarreau31936852010-10-06 16:59:56 +02002665 if (defproxy.cookie_maxidle)
2666 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2667
2668 if (defproxy.cookie_maxlife)
2669 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2670
Emeric Brun647caf12009-06-30 17:57:00 +02002671 if (defproxy.rdp_cookie_name)
2672 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2673 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2674
Willy Tarreau01732802007-11-01 22:48:15 +01002675 if (defproxy.url_param_name)
2676 curproxy->url_param_name = strdup(defproxy.url_param_name);
2677 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002678
Benoitaffb4812009-03-25 13:02:10 +01002679 if (defproxy.hh_name)
2680 curproxy->hh_name = strdup(defproxy.hh_name);
2681 curproxy->hh_len = defproxy.hh_len;
2682 curproxy->hh_match_domain = defproxy.hh_match_domain;
2683
Willy Tarreauef9a3602012-12-08 22:29:20 +01002684 if (defproxy.conn_src.iface_name)
2685 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2686 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002687 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002688#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002689 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002690#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002691 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002694 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695 if (defproxy.capture_name)
2696 curproxy->capture_name = strdup(defproxy.capture_name);
2697 curproxy->capture_namelen = defproxy.capture_namelen;
2698 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700
Willy Tarreau977b8e42006-12-29 14:19:17 +01002701 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002702 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002703 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002704 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002705 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002706 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002707 curproxy->mon_net = defproxy.mon_net;
2708 curproxy->mon_mask = defproxy.mon_mask;
2709 if (defproxy.monitor_uri)
2710 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2711 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002712 if (defproxy.defbe.name)
2713 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002714
2715 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002716 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2717 if (curproxy->conf.logformat_string &&
2718 curproxy->conf.logformat_string != default_http_log_format &&
2719 curproxy->conf.logformat_string != default_tcp_log_format &&
2720 curproxy->conf.logformat_string != clf_http_log_format)
2721 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2722
2723 if (defproxy.conf.lfs_file) {
2724 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2725 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2726 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002727
2728 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2729 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2730 if (curproxy->conf.logformat_sd_string &&
2731 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2732 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2733
2734 if (defproxy.conf.lfsd_file) {
2735 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2736 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2737 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738 }
2739
2740 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002741 curproxy->timeout.connect = defproxy.timeout.connect;
2742 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002743 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002744 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002745 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002746 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002747 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002748 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002749 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002750 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002751 }
2752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002754 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002755
2756 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002757 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002758 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002759 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002760 LIST_INIT(&node->list);
2761 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2762 }
2763
Willy Tarreau62a61232013-04-12 18:13:46 +02002764 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2765 if (curproxy->conf.uniqueid_format_string)
2766 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2767
Dragan Dosen43885c72015-10-01 13:18:13 +02002768 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002769
Willy Tarreau62a61232013-04-12 18:13:46 +02002770 if (defproxy.conf.uif_file) {
2771 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2772 curproxy->conf.uif_line = defproxy.conf.uif_line;
2773 }
William Lallemanda73203e2012-03-12 12:48:57 +01002774
2775 /* copy default header unique id */
2776 if (defproxy.header_unique_id)
2777 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2778
William Lallemand82fe75c2012-10-23 10:25:10 +02002779 /* default compression options */
2780 if (defproxy.comp != NULL) {
2781 curproxy->comp = calloc(1, sizeof(struct comp));
2782 curproxy->comp->algos = defproxy.comp->algos;
2783 curproxy->comp->types = defproxy.comp->types;
2784 }
2785
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002787 curproxy->conf.used_listener_id = EB_ROOT;
2788 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002789
Simon Horman98637e52014-06-20 12:30:16 +09002790 if (defproxy.check_path)
2791 curproxy->check_path = strdup(defproxy.check_path);
2792 if (defproxy.check_command)
2793 curproxy->check_command = strdup(defproxy.check_command);
2794
Simon Horman9dc49962015-01-30 11:22:59 +09002795 if (defproxy.email_alert.mailers.name)
2796 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2797 if (defproxy.email_alert.from)
2798 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2799 if (defproxy.email_alert.to)
2800 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2801 if (defproxy.email_alert.myhostname)
2802 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002803 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002804 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002805
Willy Tarreau93893792009-07-23 13:19:11 +02002806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 }
2808 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2809 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002810 /* FIXME-20070101: we should do this too at the end of the
2811 * config parsing to free all default values.
2812 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002813 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2814 err_code |= ERR_ABORT;
2815 goto out;
2816 }
2817
Willy Tarreaua534fea2008-08-03 12:19:50 +02002818 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002819 free(defproxy.check_command);
2820 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002821 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002822 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002823 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002824 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002825 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002826 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002827 free(defproxy.capture_name);
2828 free(defproxy.monitor_uri);
2829 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002830 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002831 free(defproxy.fwdfor_hdr_name);
2832 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002833 free(defproxy.orgto_hdr_name);
2834 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002835 free(defproxy.server_id_hdr_name);
2836 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002837 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002838 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002839 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002840 free(defproxy.expect_regex);
2841 defproxy.expect_regex = NULL;
2842 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002843
Willy Tarreau62a61232013-04-12 18:13:46 +02002844 if (defproxy.conf.logformat_string != default_http_log_format &&
2845 defproxy.conf.logformat_string != default_tcp_log_format &&
2846 defproxy.conf.logformat_string != clf_http_log_format)
2847 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002848
Willy Tarreau62a61232013-04-12 18:13:46 +02002849 free(defproxy.conf.uniqueid_format_string);
2850 free(defproxy.conf.lfs_file);
2851 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002852 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002853 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002854
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002855 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2856 free(defproxy.conf.logformat_sd_string);
2857 free(defproxy.conf.lfsd_file);
2858
Willy Tarreaua534fea2008-08-03 12:19:50 +02002859 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002860 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002861
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 /* we cannot free uri_auth because it might already be used */
2863 init_default_instance();
2864 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002865 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2866 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002867 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 }
2870 else if (curproxy == NULL) {
2871 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002875
2876 /* update the current file and line being parsed */
2877 curproxy->conf.args.file = curproxy->conf.file;
2878 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002879
2880 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002881 if (!strcmp(args[0], "server") ||
2882 !strcmp(args[0], "default-server") ||
2883 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002884 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2885 if (err_code & ERR_FATAL)
2886 goto out;
2887 }
2888 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002889 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002890 int cur_arg;
2891
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 if (curproxy == &defproxy) {
2893 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899
Willy Tarreau24709282013-03-10 21:32:12 +01002900 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002901 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002906
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002907 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002908
2909 /* use default settings for unix sockets */
2910 bind_conf->ux.uid = global.unix_bind.ux.uid;
2911 bind_conf->ux.gid = global.unix_bind.ux.gid;
2912 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002913
2914 /* NOTE: the following line might create several listeners if there
2915 * are comma-separated IPs or port ranges. So all further processing
2916 * will have to be applied to all listeners created after last_listen.
2917 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002918 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2919 if (errmsg && *errmsg) {
2920 indent_msg(&errmsg, 2);
2921 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002922 }
2923 else
2924 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2925 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002929
Willy Tarreau4348fad2012-09-20 16:48:07 +02002930 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2931 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002932 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002933 }
2934
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002935 cur_arg = 2;
2936 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002937 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002938 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002939 char *err;
2940
Willy Tarreau26982662012-09-12 23:17:10 +02002941 kw = bind_find_kw(args[cur_arg]);
2942 if (kw) {
2943 char *err = NULL;
2944 int code;
2945
2946 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002947 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2948 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002949 cur_arg += 1 + kw->skip ;
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953
Willy Tarreau4348fad2012-09-20 16:48:07 +02002954 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002955 err_code |= code;
2956
2957 if (code) {
2958 if (err && *err) {
2959 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002960 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002961 }
2962 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002963 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2964 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002965 if (code & ERR_FATAL) {
2966 free(err);
2967 cur_arg += 1 + kw->skip;
2968 goto out;
2969 }
2970 }
2971 free(err);
2972 cur_arg += 1 + kw->skip;
2973 continue;
2974 }
2975
Willy Tarreau8638f482012-09-18 18:01:17 +02002976 err = NULL;
2977 if (!bind_dumped) {
2978 bind_dump_kws(&err);
2979 indent_msg(&err, 4);
2980 bind_dumped = 1;
2981 }
2982
2983 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2984 file, linenum, args[0], args[1], args[cur_arg],
2985 err ? " Registered keywords :" : "", err ? err : "");
2986 free(err);
2987
Willy Tarreau93893792009-07-23 13:19:11 +02002988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002990 }
Willy Tarreau93893792009-07-23 13:19:11 +02002991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 }
2993 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002994 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2996 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 /* flush useless bits */
3004 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003007 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003010
William Lallemanddf1425a2015-04-28 20:17:49 +02003011 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3012 goto out;
3013
Willy Tarreau1c47f852006-07-09 08:22:27 +02003014 if (!*args[1]) {
3015 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003019 }
3020
Willy Tarreaua534fea2008-08-03 12:19:50 +02003021 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003022 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003023 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003024 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003025 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3026
Willy Tarreau93893792009-07-23 13:19:11 +02003027 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003030 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3031 goto out;
3032
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3034 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3035 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3036 else {
3037 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
3041 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003042 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003043 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003044
3045 if (curproxy == &defproxy) {
3046 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003050 }
3051
William Lallemanddf1425a2015-04-28 20:17:49 +02003052 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3053 goto out;
3054
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003055 if (!*args[1]) {
3056 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003060 }
3061
3062 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003063 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003064 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003065
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003066 if (curproxy->uuid <= 0) {
3067 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003068 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003071 }
3072
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003073 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3074 if (node) {
3075 struct proxy *target = container_of(node, struct proxy, conf.id);
3076 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3077 file, linenum, proxy_type_str(curproxy), curproxy->id,
3078 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003083 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003084 else if (!strcmp(args[0], "description")) {
3085 int i, len=0;
3086 char *d;
3087
Cyril Bonté99ed3272010-01-24 23:29:44 +01003088 if (curproxy == &defproxy) {
3089 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3090 file, linenum, args[0]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003095 if (!*args[1]) {
3096 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3097 file, linenum, args[0]);
3098 return -1;
3099 }
3100
Willy Tarreau348acfe2014-04-14 15:00:39 +02003101 for (i = 1; *args[i]; i++)
3102 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003103
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003104 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003105 curproxy->desc = d;
3106
Willy Tarreau348acfe2014-04-14 15:00:39 +02003107 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3108 for (i = 2; *args[i]; i++)
3109 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003110
3111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003113 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 curproxy->state = PR_STSTOPPED;
3116 }
3117 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003118 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 curproxy->state = PR_STNEW;
3121 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003122 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3123 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003124 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003125
3126 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003127 unsigned int low, high;
3128
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003129 if (strcmp(args[cur_arg], "all") == 0) {
3130 set = 0;
3131 break;
3132 }
3133 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003134 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003135 }
3136 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003137 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003138 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003139 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003140 char *dash = strchr(args[cur_arg], '-');
3141
3142 low = high = str2uic(args[cur_arg]);
3143 if (dash)
3144 high = str2uic(dash + 1);
3145
3146 if (high < low) {
3147 unsigned int swap = low;
3148 low = high;
3149 high = swap;
3150 }
3151
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003152 if (low < 1 || high > LONGBITS) {
3153 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3154 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003157 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003158 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003159 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003160 }
3161 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003162 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3163 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003166 }
3167 cur_arg++;
3168 }
3169 curproxy->bind_proc = set;
3170 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003171 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003172 if (curproxy == &defproxy) {
3173 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003176 }
3177
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003178 err = invalid_char(args[1]);
3179 if (err) {
3180 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3181 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003183 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003184 }
3185
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003186 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003187 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3188 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003191 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003192 }
3193 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3194
3195 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3196 err_code |= ERR_WARN;
3197
3198 if (*(args[1]) == 0) {
3199 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3200 file, linenum, args[0]);
3201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
3203 }
3204 free(curproxy->dyncookie_key);
3205 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3208 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209
Willy Tarreau977b8e42006-12-29 14:19:17 +01003210 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003212
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 if (*(args[1]) == 0) {
3214 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003219
Willy Tarreau67402132012-05-31 20:40:20 +02003220 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003221 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003222 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003223 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 curproxy->cookie_name = strdup(args[1]);
3225 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003226
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 cur_arg = 2;
3228 while (*(args[cur_arg])) {
3229 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003230 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 }
3232 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003233 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 }
3235 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003236 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 }
3238 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003239 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 }
3241 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003242 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003244 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003245 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003248 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003250 else if (!strcmp(args[cur_arg], "httponly")) {
3251 curproxy->ck_opts |= PR_CK_HTTPONLY;
3252 }
3253 else if (!strcmp(args[cur_arg], "secure")) {
3254 curproxy->ck_opts |= PR_CK_SECURE;
3255 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003256 else if (!strcmp(args[cur_arg], "domain")) {
3257 if (!*args[cur_arg + 1]) {
3258 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3259 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003262 }
3263
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003264 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003265 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003266 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3267 " dots nor does not start with a dot."
3268 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003269 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003270 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003271 }
3272
3273 err = invalid_domainchar(args[cur_arg + 1]);
3274 if (err) {
3275 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3276 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003279 }
3280
Willy Tarreau68a897b2009-12-03 23:28:34 +01003281 if (!curproxy->cookie_domain) {
3282 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3283 } else {
3284 /* one domain was already specified, add another one by
3285 * building the string which will be returned along with
3286 * the cookie.
3287 */
3288 char *new_ptr;
3289 int new_len = strlen(curproxy->cookie_domain) +
3290 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3291 new_ptr = malloc(new_len);
3292 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3293 free(curproxy->cookie_domain);
3294 curproxy->cookie_domain = new_ptr;
3295 }
Willy Tarreau31936852010-10-06 16:59:56 +02003296 cur_arg++;
3297 }
3298 else if (!strcmp(args[cur_arg], "maxidle")) {
3299 unsigned int maxidle;
3300 const char *res;
3301
3302 if (!*args[cur_arg + 1]) {
3303 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3304 file, linenum, args[cur_arg]);
3305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
3307 }
3308
3309 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3310 if (res) {
3311 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3312 file, linenum, *res, args[cur_arg]);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316 curproxy->cookie_maxidle = maxidle;
3317 cur_arg++;
3318 }
3319 else if (!strcmp(args[cur_arg], "maxlife")) {
3320 unsigned int maxlife;
3321 const char *res;
3322
3323 if (!*args[cur_arg + 1]) {
3324 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3325 file, linenum, args[cur_arg]);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
3328 }
3329
3330 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3331 if (res) {
3332 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3333 file, linenum, *res, args[cur_arg]);
3334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
3336 }
3337 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003338 cur_arg++;
3339 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003340 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003341
3342 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3343 err_code |= ERR_WARN;
3344 curproxy->ck_opts |= PR_CK_DYNAMIC;
3345 }
3346
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003348 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
3353 cur_arg++;
3354 }
Willy Tarreau67402132012-05-31 20:40:20 +02003355 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3357 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
3360
Willy Tarreau67402132012-05-31 20:40:20 +02003361 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3363 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003366
Willy Tarreau67402132012-05-31 20:40:20 +02003367 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003368 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3369 file, linenum);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003373 else if (!strcmp(args[0], "email-alert")) {
3374 if (*(args[1]) == 0) {
3375 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3376 file, linenum, args[0]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380
3381 if (!strcmp(args[1], "from")) {
3382 if (*(args[1]) == 0) {
3383 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3384 file, linenum, args[1]);
3385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388 free(curproxy->email_alert.from);
3389 curproxy->email_alert.from = strdup(args[2]);
3390 }
3391 else if (!strcmp(args[1], "mailers")) {
3392 if (*(args[1]) == 0) {
3393 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3394 file, linenum, args[1]);
3395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
3397 }
3398 free(curproxy->email_alert.mailers.name);
3399 curproxy->email_alert.mailers.name = strdup(args[2]);
3400 }
3401 else if (!strcmp(args[1], "myhostname")) {
3402 if (*(args[1]) == 0) {
3403 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3404 file, linenum, args[1]);
3405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408 free(curproxy->email_alert.myhostname);
3409 curproxy->email_alert.myhostname = strdup(args[2]);
3410 }
Simon Horman64e34162015-02-06 11:11:57 +09003411 else if (!strcmp(args[1], "level")) {
3412 curproxy->email_alert.level = get_log_level(args[2]);
3413 if (curproxy->email_alert.level < 0) {
3414 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3415 file, linenum, args[1], args[2]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419 }
Simon Horman9dc49962015-01-30 11:22:59 +09003420 else if (!strcmp(args[1], "to")) {
3421 if (*(args[1]) == 0) {
3422 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3423 file, linenum, args[1]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427 free(curproxy->email_alert.to);
3428 curproxy->email_alert.to = strdup(args[2]);
3429 }
3430 else {
3431 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3432 file, linenum, args[1]);
3433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
3435 }
Simon Horman64e34162015-02-06 11:11:57 +09003436 /* Indicate that the email_alert is at least partially configured */
3437 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003438 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003439 else if (!strcmp(args[0], "external-check")) {
3440 if (*(args[1]) == 0) {
3441 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3442 file, linenum, args[0]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446
3447 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003448 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003449 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003450 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003451 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3452 file, linenum, args[1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 free(curproxy->check_command);
3457 curproxy->check_command = strdup(args[2]);
3458 }
3459 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003460 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003461 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003462 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003463 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3464 file, linenum, args[1]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468 free(curproxy->check_path);
3469 curproxy->check_path = strdup(args[2]);
3470 }
3471 else {
3472 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3473 file, linenum, args[1]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
3477 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003478 else if (!strcmp(args[0], "persist")) { /* persist */
3479 if (*(args[1]) == 0) {
3480 Alert("parsing [%s:%d] : missing persist method.\n",
3481 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003484 }
3485
3486 if (!strncmp(args[1], "rdp-cookie", 10)) {
3487 curproxy->options2 |= PR_O2_RDPC_PRST;
3488
Emeric Brunb982a3d2010-01-04 15:45:53 +01003489 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003490 const char *beg, *end;
3491
3492 beg = args[1] + 11;
3493 end = strchr(beg, ')');
3494
William Lallemanddf1425a2015-04-28 20:17:49 +02003495 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3496 goto out;
3497
Emeric Brun647caf12009-06-30 17:57:00 +02003498 if (!end || end == beg) {
3499 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3500 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003503 }
3504
3505 free(curproxy->rdp_cookie_name);
3506 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3507 curproxy->rdp_cookie_len = end-beg;
3508 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003509 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003510 free(curproxy->rdp_cookie_name);
3511 curproxy->rdp_cookie_name = strdup("msts");
3512 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3513 }
3514 else { /* syntax */
3515 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3516 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003519 }
3520 }
3521 else {
3522 Alert("parsing [%s:%d] : unknown persist method.\n",
3523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003526 }
3527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003529 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
3532 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003533 else if (!strcmp(args[0], "load-server-state-from-file")) {
3534 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3535 err_code |= ERR_WARN;
3536 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3537 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3538 }
3539 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3540 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3541 }
3542 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3543 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3544 }
3545 else {
3546 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3547 file, linenum, args[0], args[1]);
3548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
3550 }
3551 }
3552 else if (!strcmp(args[0], "server-state-file-name")) {
3553 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3554 err_code |= ERR_WARN;
3555 if (*(args[1]) == 0) {
3556 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3557 file, linenum, args[0]);
3558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
3560 }
3561 else if (!strcmp(args[1], "use-backend-name"))
3562 curproxy->server_state_file_name = strdup(curproxy->id);
3563 else
3564 curproxy->server_state_file_name = strdup(args[1]);
3565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003567 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003569
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003571 if (curproxy == &defproxy) {
3572 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
3575 }
3576
William Lallemand1a748ae2015-05-19 16:37:23 +02003577 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3578 goto out;
3579
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 if (*(args[4]) == 0) {
3581 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003586 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 curproxy->capture_name = strdup(args[2]);
3588 curproxy->capture_namelen = strlen(curproxy->capture_name);
3589 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 curproxy->to_log |= LW_COOKIE;
3591 }
3592 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3593 struct cap_hdr *hdr;
3594
3595 if (curproxy == &defproxy) {
3596 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 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 }
3600
William Lallemand1a748ae2015-05-19 16:37:23 +02003601 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3602 goto out;
3603
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3605 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3606 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
3610
Vincent Bernat02779b62016-04-03 13:48:43 +02003611 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 hdr->next = curproxy->req_cap;
3613 hdr->name = strdup(args[3]);
3614 hdr->namelen = strlen(args[3]);
3615 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003616 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 hdr->index = curproxy->nb_req_cap++;
3618 curproxy->req_cap = hdr;
3619 curproxy->to_log |= LW_REQHDR;
3620 }
3621 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3622 struct cap_hdr *hdr;
3623
3624 if (curproxy == &defproxy) {
3625 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 +02003626 err_code |= ERR_ALERT | ERR_FATAL;
3627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 }
3629
William Lallemand1a748ae2015-05-19 16:37:23 +02003630 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3631 goto out;
3632
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3634 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3635 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003639 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 hdr->next = curproxy->rsp_cap;
3641 hdr->name = strdup(args[3]);
3642 hdr->namelen = strlen(args[3]);
3643 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003644 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 hdr->index = curproxy->nb_rsp_cap++;
3646 curproxy->rsp_cap = hdr;
3647 curproxy->to_log |= LW_RSPHDR;
3648 }
3649 else {
3650 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 }
3655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003659
William Lallemanddf1425a2015-04-28 20:17:49 +02003660 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3661 goto out;
3662
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 if (*(args[1]) == 0) {
3664 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 }
3669 curproxy->conn_retries = atol(args[1]);
3670 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003671 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003672 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003673
3674 if (curproxy == &defproxy) {
3675 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
3678 }
3679
Willy Tarreau20b0de52012-12-24 15:45:22 +01003680 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003681 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003682 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3683 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3684 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3685 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003686 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 +01003687 file, linenum, args[0]);
3688 err_code |= ERR_WARN;
3689 }
3690
Willy Tarreauff011f22011-01-06 17:51:27 +01003691 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003692
Willy Tarreauff011f22011-01-06 17:51:27 +01003693 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003694 err_code |= ERR_ALERT | ERR_ABORT;
3695 goto out;
3696 }
3697
Willy Tarreau5002f572014-04-23 01:32:02 +02003698 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003699 err_code |= warnif_cond_conflicts(rule->cond,
3700 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3701 file, linenum);
3702
Willy Tarreauff011f22011-01-06 17:51:27 +01003703 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003704 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003705 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003706 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003707
3708 if (curproxy == &defproxy) {
3709 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
3712 }
3713
3714 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003715 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003716 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3717 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003718 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3719 file, linenum, args[0]);
3720 err_code |= ERR_WARN;
3721 }
3722
3723 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3724
3725 if (!rule) {
3726 err_code |= ERR_ALERT | ERR_ABORT;
3727 goto out;
3728 }
3729
3730 err_code |= warnif_cond_conflicts(rule->cond,
3731 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3732 file, linenum);
3733
3734 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3735 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003736 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3737 /* set the header name and length into the proxy structure */
3738 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3739 err_code |= ERR_WARN;
3740
3741 if (!*args[1]) {
3742 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3743 file, linenum, args[0]);
3744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
3746 }
3747
3748 /* set the desired header name */
3749 free(curproxy->server_id_hdr_name);
3750 curproxy->server_id_hdr_name = strdup(args[1]);
3751 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3752 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003753 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003754 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003755
Willy Tarreaub099aca2008-10-12 17:26:37 +02003756 if (curproxy == &defproxy) {
3757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003760 }
3761
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003762 /* emulate "block" using "http-request block". Since these rules are supposed to
3763 * be processed before all http-request rules, we put them into their own list
3764 * and will insert them at the end.
3765 */
3766 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3767 if (!rule) {
3768 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003769 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003770 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003771 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3772 err_code |= warnif_cond_conflicts(rule->cond,
3773 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3774 file, linenum);
3775 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003776
3777 if (!already_warned(WARN_BLOCK_DEPRECATED))
3778 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]);
3779
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003780 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003781 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003782 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003783
Cyril Bonté99ed3272010-01-24 23:29:44 +01003784 if (curproxy == &defproxy) {
3785 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
3788 }
3789
Willy Tarreaube4653b2015-05-28 15:26:58 +02003790 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003791 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3792 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003795 }
3796
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003797 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003798 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003799 err_code |= warnif_cond_conflicts(rule->cond,
3800 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3801 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003802 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003803 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003804 struct switching_rule *rule;
3805
Willy Tarreaub099aca2008-10-12 17:26:37 +02003806 if (curproxy == &defproxy) {
3807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003810 }
3811
Willy Tarreau55ea7572007-06-17 19:56:27 +02003812 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003814
3815 if (*(args[1]) == 0) {
3816 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003819 }
3820
Willy Tarreauf51658d2014-04-23 01:21:56 +02003821 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3822 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3823 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3824 file, linenum, errmsg);
3825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
3827 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003828
Willy Tarreauf51658d2014-04-23 01:21:56 +02003829 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003830 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003831 else if (*args[2]) {
3832 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3833 file, linenum, args[2]);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003837
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003838 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003839 if (!rule) {
3840 Alert("Out of memory error.\n");
3841 goto out;
3842 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003843 rule->cond = cond;
3844 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003845 rule->line = linenum;
3846 rule->file = strdup(file);
3847 if (!rule->file) {
3848 Alert("Out of memory error.\n");
3849 goto out;
3850 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003851 LIST_INIT(&rule->list);
3852 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3853 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003854 else if (strcmp(args[0], "use-server") == 0) {
3855 struct server_rule *rule;
3856
3857 if (curproxy == &defproxy) {
3858 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
3861 }
3862
3863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3864 err_code |= ERR_WARN;
3865
3866 if (*(args[1]) == 0) {
3867 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
3870 }
3871
3872 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3873 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3874 file, linenum, args[0]);
3875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003879 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3880 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3881 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
3885
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003886 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003887
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003888 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003889 rule->cond = cond;
3890 rule->srv.name = strdup(args[1]);
3891 LIST_INIT(&rule->list);
3892 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3893 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3894 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003895 else if ((!strcmp(args[0], "force-persist")) ||
3896 (!strcmp(args[0], "ignore-persist"))) {
3897 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003898
3899 if (curproxy == &defproxy) {
3900 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
3903 }
3904
3905 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3906 err_code |= ERR_WARN;
3907
Willy Tarreauef6494c2010-01-28 17:12:36 +01003908 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003909 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3910 file, linenum, args[0]);
3911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
3913 }
3914
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003915 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3916 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3917 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
3920 }
3921
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003922 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3923 * where force-persist is applied.
3924 */
3925 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003926
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003927 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003928 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003929 if (!strcmp(args[0], "force-persist")) {
3930 rule->type = PERSIST_TYPE_FORCE;
3931 } else {
3932 rule->type = PERSIST_TYPE_IGNORE;
3933 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003934 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003935 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003936 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003937 else if (!strcmp(args[0], "stick-table")) {
3938 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003939 struct proxy *other;
3940
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003941 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003942 if (other) {
3943 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3944 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003948
Emeric Brun32da3c42010-09-23 18:39:19 +02003949 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003950 curproxy->table.type = (unsigned int)-1;
3951 while (*args[myidx]) {
3952 const char *err;
3953
3954 if (strcmp(args[myidx], "size") == 0) {
3955 myidx++;
3956 if (!*(args[myidx])) {
3957 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3958 file, linenum, args[myidx-1]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3963 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3964 file, linenum, *err, args[myidx-1]);
3965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003968 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003969 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003970 else if (strcmp(args[myidx], "peers") == 0) {
3971 myidx++;
Godbach50523162013-12-11 19:48:57 +08003972 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003973 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3974 file, linenum, args[myidx-1]);
3975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Godbach50523162013-12-11 19:48:57 +08003977 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003978 curproxy->table.peers.name = strdup(args[myidx++]);
3979 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003980 else if (strcmp(args[myidx], "expire") == 0) {
3981 myidx++;
3982 if (!*(args[myidx])) {
3983 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3984 file, linenum, args[myidx-1]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
3988 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3989 if (err) {
3990 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3991 file, linenum, *err, args[myidx-1]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003995 if (val > INT_MAX) {
3996 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3997 file, linenum, val);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004001 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004002 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004003 }
4004 else if (strcmp(args[myidx], "nopurge") == 0) {
4005 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004006 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004007 }
4008 else if (strcmp(args[myidx], "type") == 0) {
4009 myidx++;
4010 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4011 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4012 file, linenum, args[myidx]);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004016 /* myidx already points to next arg */
4017 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004018 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004019 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004020 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004021
4022 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004023 nw = args[myidx];
4024 while (*nw) {
4025 /* the "store" keyword supports a comma-separated list */
4026 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004027 sa = NULL; /* store arg */
4028 while (*nw && *nw != ',') {
4029 if (*nw == '(') {
4030 *nw = 0;
4031 sa = ++nw;
4032 while (*nw != ')') {
4033 if (!*nw) {
4034 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4035 file, linenum, args[0], cw);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039 nw++;
4040 }
4041 *nw = '\0';
4042 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004043 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004044 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004045 if (*nw)
4046 *nw++ = '\0';
4047 type = stktable_get_data_type(cw);
4048 if (type < 0) {
4049 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4050 file, linenum, args[0], cw);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
Willy Tarreauac782882010-06-20 10:41:54 +02004054
4055 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4056 switch (err) {
4057 case PE_NONE: break;
4058 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004059 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4060 file, linenum, args[0], cw);
4061 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004062 break;
4063
4064 case PE_ARG_MISSING:
4065 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4066 file, linenum, args[0], cw);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069
4070 case PE_ARG_NOT_USED:
4071 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4072 file, linenum, args[0], cw);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075
4076 default:
4077 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4078 file, linenum, args[0], cw);
4079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004081 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004082 }
4083 myidx++;
4084 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004085 else {
4086 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4087 file, linenum, args[myidx]);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004090 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004091 }
4092
4093 if (!curproxy->table.size) {
4094 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4095 file, linenum);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
4099
4100 if (curproxy->table.type == (unsigned int)-1) {
4101 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4102 file, linenum);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 }
4107 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004108 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004109 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004110 int myidx = 0;
4111 const char *name = NULL;
4112 int flags;
4113
4114 if (curproxy == &defproxy) {
4115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119
4120 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4121 err_code |= ERR_WARN;
4122 goto out;
4123 }
4124
4125 myidx++;
4126 if ((strcmp(args[myidx], "store") == 0) ||
4127 (strcmp(args[myidx], "store-request") == 0)) {
4128 myidx++;
4129 flags = STK_IS_STORE;
4130 }
4131 else if (strcmp(args[myidx], "store-response") == 0) {
4132 myidx++;
4133 flags = STK_IS_STORE | STK_ON_RSP;
4134 }
4135 else if (strcmp(args[myidx], "match") == 0) {
4136 myidx++;
4137 flags = STK_IS_MATCH;
4138 }
4139 else if (strcmp(args[myidx], "on") == 0) {
4140 myidx++;
4141 flags = STK_IS_MATCH | STK_IS_STORE;
4142 }
4143 else {
4144 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
4147 }
4148
4149 if (*(args[myidx]) == 0) {
4150 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004155 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004156 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004157 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004158 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
4161 }
4162
4163 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004164 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4165 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4166 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004167 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004168 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004169 goto out;
4170 }
4171 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004172 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4173 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4174 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004175 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004176 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004177 goto out;
4178 }
4179 }
4180
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004181 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004182 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004183
Emeric Brunb982a3d2010-01-04 15:45:53 +01004184 if (strcmp(args[myidx], "table") == 0) {
4185 myidx++;
4186 name = args[myidx++];
4187 }
4188
Willy Tarreauef6494c2010-01-28 17:12:36 +01004189 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004190 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4191 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4192 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004193 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004194 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004195 goto out;
4196 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004197 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004198 else if (*(args[myidx])) {
4199 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4200 file, linenum, args[0], args[myidx]);
4201 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004202 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004203 goto out;
4204 }
Emeric Brun97679e72010-09-23 17:56:44 +02004205 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004206 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004207 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004208 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004209
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004210 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004211 rule->cond = cond;
4212 rule->expr = expr;
4213 rule->flags = flags;
4214 rule->table.name = name ? strdup(name) : NULL;
4215 LIST_INIT(&rule->list);
4216 if (flags & STK_ON_RSP)
4217 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4218 else
4219 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 else if (!strcmp(args[0], "stats")) {
4222 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4223 curproxy->uri_auth = NULL; /* we must detach from the default config */
4224
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004225 if (!*args[1]) {
4226 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004227 } else if (!strcmp(args[1], "admin")) {
4228 struct stats_admin_rule *rule;
4229
4230 if (curproxy == &defproxy) {
4231 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235
4236 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4237 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4238 err_code |= ERR_ALERT | ERR_ABORT;
4239 goto out;
4240 }
4241
4242 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4243 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4244 file, linenum, args[0], args[1]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004248 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4249 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4250 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
4254
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004255 err_code |= warnif_cond_conflicts(cond,
4256 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4257 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004258
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004259 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004260 rule->cond = cond;
4261 LIST_INIT(&rule->list);
4262 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 } else if (!strcmp(args[1], "uri")) {
4264 if (*(args[2]) == 0) {
4265 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004268 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4269 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004270 err_code |= ERR_ALERT | ERR_ABORT;
4271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004272 }
4273 } else if (!strcmp(args[1], "realm")) {
4274 if (*(args[2]) == 0) {
4275 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_ABORT;
4281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004283 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004284 unsigned interval;
4285
4286 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4287 if (err) {
4288 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4289 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004292 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_ABORT;
4295 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004296 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004297 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004298 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004299
4300 if (curproxy == &defproxy) {
4301 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
4304 }
4305
4306 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4307 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4308 err_code |= ERR_ALERT | ERR_ABORT;
4309 goto out;
4310 }
4311
Willy Tarreauff011f22011-01-06 17:51:27 +01004312 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004313 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004314 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4315 file, linenum, args[0]);
4316 err_code |= ERR_WARN;
4317 }
4318
Willy Tarreauff011f22011-01-06 17:51:27 +01004319 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004320
Willy Tarreauff011f22011-01-06 17:51:27 +01004321 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004322 err_code |= ERR_ALERT | ERR_ABORT;
4323 goto out;
4324 }
4325
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004326 err_code |= warnif_cond_conflicts(rule->cond,
4327 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4328 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004329 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004330
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 } else if (!strcmp(args[1], "auth")) {
4332 if (*(args[2]) == 0) {
4333 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4337 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004338 err_code |= ERR_ALERT | ERR_ABORT;
4339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 }
4341 } else if (!strcmp(args[1], "scope")) {
4342 if (*(args[2]) == 0) {
4343 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4347 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004348 err_code |= ERR_ALERT | ERR_ABORT;
4349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350 }
4351 } else if (!strcmp(args[1], "enable")) {
4352 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4353 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_ABORT;
4355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004357 } else if (!strcmp(args[1], "hide-version")) {
4358 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_ABORT;
4361 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004362 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004363 } else if (!strcmp(args[1], "show-legends")) {
4364 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4365 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4366 err_code |= ERR_ALERT | ERR_ABORT;
4367 goto out;
4368 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004369 } else if (!strcmp(args[1], "show-node")) {
4370
4371 if (*args[2]) {
4372 int i;
4373 char c;
4374
4375 for (i=0; args[2][i]; i++) {
4376 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004377 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4378 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004379 break;
4380 }
4381
4382 if (!i || args[2][i]) {
4383 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4384 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4385 file, linenum, args[0], args[1]);
4386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
4388 }
4389 }
4390
4391 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4392 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4393 err_code |= ERR_ALERT | ERR_ABORT;
4394 goto out;
4395 }
4396 } else if (!strcmp(args[1], "show-desc")) {
4397 char *desc = NULL;
4398
4399 if (*args[2]) {
4400 int i, len=0;
4401 char *d;
4402
Willy Tarreau348acfe2014-04-14 15:00:39 +02004403 for (i = 2; *args[i]; i++)
4404 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004405
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004406 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004407
Willy Tarreau348acfe2014-04-14 15:00:39 +02004408 d += snprintf(d, desc + len - d, "%s", args[2]);
4409 for (i = 3; *args[i]; i++)
4410 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004411 }
4412
4413 if (!*args[2] && !global.desc)
4414 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4415 file, linenum, args[1]);
4416 else {
4417 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4418 free(desc);
4419 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4420 err_code |= ERR_ALERT | ERR_ABORT;
4421 goto out;
4422 }
4423 free(desc);
4424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004426stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004427 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 +01004428 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 }
4432 }
4433 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004434 int optnum;
4435
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004436 if (*(args[1]) == '\0') {
4437 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4438 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004442
4443 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4444 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004445 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4446 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4447 file, linenum, cfg_opts[optnum].name);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004451 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4452 goto out;
4453
Willy Tarreau93893792009-07-23 13:19:11 +02004454 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4455 err_code |= ERR_WARN;
4456 goto out;
4457 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004458
Willy Tarreau3842f002009-06-14 11:39:52 +02004459 curproxy->no_options &= ~cfg_opts[optnum].val;
4460 curproxy->options &= ~cfg_opts[optnum].val;
4461
4462 switch (kwm) {
4463 case KWM_STD:
4464 curproxy->options |= cfg_opts[optnum].val;
4465 break;
4466 case KWM_NO:
4467 curproxy->no_options |= cfg_opts[optnum].val;
4468 break;
4469 case KWM_DEF: /* already cleared */
4470 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004471 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004472
Willy Tarreau93893792009-07-23 13:19:11 +02004473 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004474 }
4475 }
4476
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004477 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4478 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004479 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4480 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4481 file, linenum, cfg_opts2[optnum].name);
4482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
4484 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004485 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4486 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004487 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4488 err_code |= ERR_WARN;
4489 goto out;
4490 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004491
Willy Tarreau3842f002009-06-14 11:39:52 +02004492 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4493 curproxy->options2 &= ~cfg_opts2[optnum].val;
4494
4495 switch (kwm) {
4496 case KWM_STD:
4497 curproxy->options2 |= cfg_opts2[optnum].val;
4498 break;
4499 case KWM_NO:
4500 curproxy->no_options2 |= cfg_opts2[optnum].val;
4501 break;
4502 case KWM_DEF: /* already cleared */
4503 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004504 }
Willy Tarreau93893792009-07-23 13:19:11 +02004505 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004506 }
4507 }
4508
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004509 /* HTTP options override each other. They can be cancelled using
4510 * "no option xxx" which only switches to default mode if the mode
4511 * was this one (useful for cancelling options set in defaults
4512 * sections).
4513 */
4514 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004515 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4516 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004517 if (kwm == KWM_STD) {
4518 curproxy->options &= ~PR_O_HTTP_MODE;
4519 curproxy->options |= PR_O_HTTP_PCL;
4520 goto out;
4521 }
4522 else if (kwm == KWM_NO) {
4523 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4524 curproxy->options &= ~PR_O_HTTP_MODE;
4525 goto out;
4526 }
4527 }
4528 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004529 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4530 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004531 if (kwm == KWM_STD) {
4532 curproxy->options &= ~PR_O_HTTP_MODE;
4533 curproxy->options |= PR_O_HTTP_FCL;
4534 goto out;
4535 }
4536 else if (kwm == KWM_NO) {
4537 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4538 curproxy->options &= ~PR_O_HTTP_MODE;
4539 goto out;
4540 }
4541 }
4542 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004543 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4544 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004545 if (kwm == KWM_STD) {
4546 curproxy->options &= ~PR_O_HTTP_MODE;
4547 curproxy->options |= PR_O_HTTP_SCL;
4548 goto out;
4549 }
4550 else if (kwm == KWM_NO) {
4551 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4552 curproxy->options &= ~PR_O_HTTP_MODE;
4553 goto out;
4554 }
4555 }
4556 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004557 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4558 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004559 if (kwm == KWM_STD) {
4560 curproxy->options &= ~PR_O_HTTP_MODE;
4561 curproxy->options |= PR_O_HTTP_KAL;
4562 goto out;
4563 }
4564 else if (kwm == KWM_NO) {
4565 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4566 curproxy->options &= ~PR_O_HTTP_MODE;
4567 goto out;
4568 }
4569 }
4570 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004571 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4572 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004573 if (kwm == KWM_STD) {
4574 curproxy->options &= ~PR_O_HTTP_MODE;
4575 curproxy->options |= PR_O_HTTP_TUN;
4576 goto out;
4577 }
4578 else if (kwm == KWM_NO) {
4579 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4580 curproxy->options &= ~PR_O_HTTP_MODE;
4581 goto out;
4582 }
4583 }
4584
Joseph Lynch726ab712015-05-11 23:25:34 -07004585 /* Redispatch can take an integer argument that control when the
4586 * resispatch occurs. All values are relative to the retries option.
4587 * This can be cancelled using "no option xxx".
4588 */
4589 if (strcmp(args[1], "redispatch") == 0) {
4590 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4591 err_code |= ERR_WARN;
4592 goto out;
4593 }
4594
4595 curproxy->no_options &= ~PR_O_REDISP;
4596 curproxy->options &= ~PR_O_REDISP;
4597
4598 switch (kwm) {
4599 case KWM_STD:
4600 curproxy->options |= PR_O_REDISP;
4601 curproxy->redispatch_after = -1;
4602 if(*args[2]) {
4603 curproxy->redispatch_after = atol(args[2]);
4604 }
4605 break;
4606 case KWM_NO:
4607 curproxy->no_options |= PR_O_REDISP;
4608 curproxy->redispatch_after = 0;
4609 break;
4610 case KWM_DEF: /* already cleared */
4611 break;
4612 }
4613 goto out;
4614 }
4615
Willy Tarreau3842f002009-06-14 11:39:52 +02004616 if (kwm != KWM_STD) {
4617 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004618 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004621 }
4622
Emeric Brun3a058f32009-06-30 18:26:00 +02004623 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004624 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004626 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004627 if (*(args[2]) != '\0') {
4628 if (!strcmp(args[2], "clf")) {
4629 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004630 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004631 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004632 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004635 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004636 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4637 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004638 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004639 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4640 char *oldlogformat = "log-format";
4641 char *clflogformat = "";
4642
4643 if (curproxy->conf.logformat_string == default_http_log_format)
4644 oldlogformat = "option httplog";
4645 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4646 oldlogformat = "option tcplog";
4647 else if (curproxy->conf.logformat_string == clf_http_log_format)
4648 oldlogformat = "option httplog clf";
4649 if (logformat == clf_http_log_format)
4650 clflogformat = " clf";
4651 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4652 file, linenum, clflogformat, oldlogformat);
4653 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004654 if (curproxy->conf.logformat_string != default_http_log_format &&
4655 curproxy->conf.logformat_string != default_tcp_log_format &&
4656 curproxy->conf.logformat_string != clf_http_log_format)
4657 free(curproxy->conf.logformat_string);
4658 curproxy->conf.logformat_string = logformat;
4659
4660 free(curproxy->conf.lfs_file);
4661 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4662 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004663 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004664 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004665 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4666 char *oldlogformat = "log-format";
4667
4668 if (curproxy->conf.logformat_string == default_http_log_format)
4669 oldlogformat = "option httplog";
4670 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4671 oldlogformat = "option tcplog";
4672 else if (curproxy->conf.logformat_string == clf_http_log_format)
4673 oldlogformat = "option httplog clf";
4674 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4675 file, linenum, oldlogformat);
4676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004678 if (curproxy->conf.logformat_string != default_http_log_format &&
4679 curproxy->conf.logformat_string != default_tcp_log_format &&
4680 curproxy->conf.logformat_string != clf_http_log_format)
4681 free(curproxy->conf.logformat_string);
4682 curproxy->conf.logformat_string = default_tcp_log_format;
4683
4684 free(curproxy->conf.lfs_file);
4685 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4686 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004687
4688 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4689 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004692 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004693 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004694 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004695
William Lallemanddf1425a2015-04-28 20:17:49 +02004696 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4697 goto out;
4698
Willy Tarreau13943ab2006-12-31 00:24:10 +01004699 if (curproxy->cap & PR_CAP_FE)
4700 curproxy->options |= PR_O_TCP_CLI_KA;
4701 if (curproxy->cap & PR_CAP_BE)
4702 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 }
4704 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004705 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004706 err_code |= ERR_WARN;
4707
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004709 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004710 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004711 curproxy->options2 &= ~PR_O2_CHK_ANY;
4712 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 if (!*args[2]) { /* no argument */
4714 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4715 curproxy->check_len = strlen(DEF_CHECK_REQ);
4716 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004717 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004718 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004719 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004720 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004722 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 if (*args[4])
4724 reqlen += strlen(args[4]);
4725 else
4726 reqlen += strlen("HTTP/1.0");
4727
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004728 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004730 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004732 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4733 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004734 }
4735 else if (!strcmp(args[1], "ssl-hello-chk")) {
4736 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004737 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004738 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004739
Willy Tarreaua534fea2008-08-03 12:19:50 +02004740 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004741 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004742 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004743 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004744
4745 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 }
Willy Tarreau23677902007-05-08 23:50:35 +02004748 else if (!strcmp(args[1], "smtpchk")) {
4749 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004750 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004751 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004752 curproxy->options2 &= ~PR_O2_CHK_ANY;
4753 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004754
4755 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4756 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4757 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4758 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4759 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4760 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004761 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004762 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4763 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4764 } else {
4765 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4766 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4767 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4768 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4769 }
4770 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004771 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4772 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004773 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004774 else if (!strcmp(args[1], "pgsql-check")) {
4775 /* use PostgreSQL request to check servers' health */
4776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4777 err_code |= ERR_WARN;
4778
4779 free(curproxy->check_req);
4780 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004781 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004782 curproxy->options2 |= PR_O2_PGSQL_CHK;
4783
4784 if (*(args[2])) {
4785 int cur_arg = 2;
4786
4787 while (*(args[cur_arg])) {
4788 if (strcmp(args[cur_arg], "user") == 0) {
4789 char * packet;
4790 uint32_t packet_len;
4791 uint32_t pv;
4792
4793 /* suboption header - needs additional argument for it */
4794 if (*(args[cur_arg+1]) == 0) {
4795 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4796 file, linenum, args[0], args[1], args[cur_arg]);
4797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
4800
4801 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4802 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4803 pv = htonl(0x30000); /* protocol version 3.0 */
4804
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004805 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004806
4807 memcpy(packet + 4, &pv, 4);
4808
4809 /* copy "user" */
4810 memcpy(packet + 8, "user", 4);
4811
4812 /* copy username */
4813 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4814
4815 free(curproxy->check_req);
4816 curproxy->check_req = packet;
4817 curproxy->check_len = packet_len;
4818
4819 packet_len = htonl(packet_len);
4820 memcpy(packet, &packet_len, 4);
4821 cur_arg += 2;
4822 } else {
4823 /* unknown suboption - catchall */
4824 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4825 file, linenum, args[0], args[1]);
4826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
4828 }
4829 } /* end while loop */
4830 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004831 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4832 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004833 }
4834
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004835 else if (!strcmp(args[1], "redis-check")) {
4836 /* use REDIS PING request to check servers' health */
4837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4838 err_code |= ERR_WARN;
4839
4840 free(curproxy->check_req);
4841 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004842 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004843 curproxy->options2 |= PR_O2_REDIS_CHK;
4844
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004845 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004846 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4847 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004848
4849 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4850 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004851 }
4852
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004853 else if (!strcmp(args[1], "mysql-check")) {
4854 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4856 err_code |= ERR_WARN;
4857
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004858 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;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004861 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004862
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004863 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004864 * const char mysql40_client_auth_pkt[] = {
4865 * "\x0e\x00\x00" // packet length
4866 * "\x01" // packet number
4867 * "\x00\x00" // client capabilities
4868 * "\x00\x00\x01" // max packet
4869 * "haproxy\x00" // username (null terminated string)
4870 * "\x00" // filler (always 0x00)
4871 * "\x01\x00\x00" // packet length
4872 * "\x00" // packet number
4873 * "\x01" // COM_QUIT command
4874 * };
4875 */
4876
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004877 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4878 * const char mysql41_client_auth_pkt[] = {
4879 * "\x0e\x00\x00\" // packet length
4880 * "\x01" // packet number
4881 * "\x00\x00\x00\x00" // client capabilities
4882 * "\x00\x00\x00\x01" // max packet
4883 * "\x21" // character set (UTF-8)
4884 * char[23] // All zeroes
4885 * "haproxy\x00" // username (null terminated string)
4886 * "\x00" // filler (always 0x00)
4887 * "\x01\x00\x00" // packet length
4888 * "\x00" // packet number
4889 * "\x01" // COM_QUIT command
4890 * };
4891 */
4892
4893
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004894 if (*(args[2])) {
4895 int cur_arg = 2;
4896
4897 while (*(args[cur_arg])) {
4898 if (strcmp(args[cur_arg], "user") == 0) {
4899 char *mysqluser;
4900 int packetlen, reqlen, userlen;
4901
4902 /* suboption header - needs additional argument for it */
4903 if (*(args[cur_arg+1]) == 0) {
4904 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4905 file, linenum, args[0], args[1], args[cur_arg]);
4906 err_code |= ERR_ALERT | ERR_FATAL;
4907 goto out;
4908 }
4909 mysqluser = args[cur_arg + 1];
4910 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004911
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004912 if (*(args[cur_arg+2])) {
4913 if (!strcmp(args[cur_arg+2], "post-41")) {
4914 packetlen = userlen + 7 + 27;
4915 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004916
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004917 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004918 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004919 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004920
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004921 snprintf(curproxy->check_req, 4, "%c%c%c",
4922 ((unsigned char) packetlen & 0xff),
4923 ((unsigned char) (packetlen >> 8) & 0xff),
4924 ((unsigned char) (packetlen >> 16) & 0xff));
4925
4926 curproxy->check_req[3] = 1;
4927 curproxy->check_req[5] = 130;
4928 curproxy->check_req[11] = 1;
4929 curproxy->check_req[12] = 33;
4930 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4931 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4932 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4933 cur_arg += 3;
4934 } else {
4935 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
4938 }
4939 } else {
4940 packetlen = userlen + 7;
4941 reqlen = packetlen + 9;
4942
4943 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004944 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004945 curproxy->check_len = reqlen;
4946
4947 snprintf(curproxy->check_req, 4, "%c%c%c",
4948 ((unsigned char) packetlen & 0xff),
4949 ((unsigned char) (packetlen >> 8) & 0xff),
4950 ((unsigned char) (packetlen >> 16) & 0xff));
4951
4952 curproxy->check_req[3] = 1;
4953 curproxy->check_req[5] = 128;
4954 curproxy->check_req[8] = 1;
4955 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4956 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4957 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4958 cur_arg += 2;
4959 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004960 } else {
4961 /* unknown suboption - catchall */
4962 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4963 file, linenum, args[0], args[1]);
4964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
4966 }
4967 } /* end while loop */
4968 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004969 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004970 else if (!strcmp(args[1], "ldap-check")) {
4971 /* use LDAP request to check servers' health */
4972 free(curproxy->check_req);
4973 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004974 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004975 curproxy->options2 |= PR_O2_LDAP_CHK;
4976
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004977 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004978 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4979 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004980 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4981 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004982 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004983 else if (!strcmp(args[1], "spop-check")) {
4984 if (curproxy == &defproxy) {
4985 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4986 file, linenum, args[0], args[1]);
4987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
4989 }
4990 if (curproxy->cap & PR_CAP_FE) {
4991 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4992 file, linenum, args[0], args[1]);
4993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
4995 }
4996
4997 /* use SPOE request to check servers' health */
4998 free(curproxy->check_req);
4999 curproxy->check_req = NULL;
5000 curproxy->options2 &= ~PR_O2_CHK_ANY;
5001 curproxy->options2 |= PR_O2_SPOP_CHK;
5002
Christopher Faulet8ef75252017-02-20 22:56:03 +01005003 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01005004 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
5005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
5007 }
5008 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5009 goto out;
5010 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005011 else if (!strcmp(args[1], "tcp-check")) {
5012 /* use raw TCPCHK send/expect to check servers' health */
5013 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5014 err_code |= ERR_WARN;
5015
5016 free(curproxy->check_req);
5017 curproxy->check_req = NULL;
5018 curproxy->options2 &= ~PR_O2_CHK_ANY;
5019 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005020 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5021 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005022 }
Simon Horman98637e52014-06-20 12:30:16 +09005023 else if (!strcmp(args[1], "external-check")) {
5024 /* excute an external command to check servers' health */
5025 free(curproxy->check_req);
5026 curproxy->check_req = NULL;
5027 curproxy->options2 &= ~PR_O2_CHK_ANY;
5028 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005029 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5030 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005031 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005032 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005033 int cur_arg;
5034
5035 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5036 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005037 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005038
Willy Tarreau87cf5142011-08-19 22:57:24 +02005039 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005040
5041 free(curproxy->fwdfor_hdr_name);
5042 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5043 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5044
5045 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5046 cur_arg = 2;
5047 while (*(args[cur_arg])) {
5048 if (!strcmp(args[cur_arg], "except")) {
5049 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005050 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005051 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5052 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005055 }
5056 /* flush useless bits */
5057 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005058 cur_arg += 2;
5059 } else if (!strcmp(args[cur_arg], "header")) {
5060 /* suboption header - needs additional argument for it */
5061 if (*(args[cur_arg+1]) == 0) {
5062 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5063 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005066 }
5067 free(curproxy->fwdfor_hdr_name);
5068 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5069 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5070 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005071 } else if (!strcmp(args[cur_arg], "if-none")) {
5072 curproxy->options &= ~PR_O_FF_ALWAYS;
5073 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005074 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005075 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005076 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005077 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005080 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005081 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005082 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005083 else if (!strcmp(args[1], "originalto")) {
5084 int cur_arg;
5085
5086 /* insert x-original-to field, but not for the IP address listed as an except.
5087 * set default options (ie: bitfield, header name, etc)
5088 */
5089
5090 curproxy->options |= PR_O_ORGTO;
5091
5092 free(curproxy->orgto_hdr_name);
5093 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5094 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5095
Willy Tarreau87cf5142011-08-19 22:57:24 +02005096 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005097 cur_arg = 2;
5098 while (*(args[cur_arg])) {
5099 if (!strcmp(args[cur_arg], "except")) {
5100 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005101 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 +02005102 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5103 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005106 }
5107 /* flush useless bits */
5108 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5109 cur_arg += 2;
5110 } else if (!strcmp(args[cur_arg], "header")) {
5111 /* suboption header - needs additional argument for it */
5112 if (*(args[cur_arg+1]) == 0) {
5113 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5114 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005117 }
5118 free(curproxy->orgto_hdr_name);
5119 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5120 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5121 cur_arg += 2;
5122 } else {
5123 /* unknown suboption - catchall */
5124 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5125 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005128 }
5129 } /* end while loop */
5130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 else {
5132 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 }
Willy Tarreau93893792009-07-23 13:19:11 +02005136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005138 else if (!strcmp(args[0], "default_backend")) {
5139 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005141
5142 if (*(args[1]) == 0) {
5143 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005146 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005147 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005148 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005149
5150 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5151 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005154 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005156
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005157 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5158 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 +01005159 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 /* enable reconnections to dispatch */
5162 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005163
5164 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005167 else if (!strcmp(args[0], "http-reuse")) {
5168 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5169 err_code |= ERR_WARN;
5170
5171 if (strcmp(args[1], "never") == 0) {
5172 /* enable a graceful server shutdown on an HTTP 404 response */
5173 curproxy->options &= ~PR_O_REUSE_MASK;
5174 curproxy->options |= PR_O_REUSE_NEVR;
5175 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5176 goto out;
5177 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005178 else if (strcmp(args[1], "safe") == 0) {
5179 /* enable a graceful server shutdown on an HTTP 404 response */
5180 curproxy->options &= ~PR_O_REUSE_MASK;
5181 curproxy->options |= PR_O_REUSE_SAFE;
5182 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5183 goto out;
5184 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005185 else if (strcmp(args[1], "aggressive") == 0) {
5186 curproxy->options &= ~PR_O_REUSE_MASK;
5187 curproxy->options |= PR_O_REUSE_AGGR;
5188 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5189 goto out;
5190 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005191 else if (strcmp(args[1], "always") == 0) {
5192 /* enable a graceful server shutdown on an HTTP 404 response */
5193 curproxy->options &= ~PR_O_REUSE_MASK;
5194 curproxy->options |= PR_O_REUSE_ALWS;
5195 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5196 goto out;
5197 }
5198 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005199 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
5203 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005204 else if (!strcmp(args[0], "http-check")) {
5205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005207
5208 if (strcmp(args[1], "disable-on-404") == 0) {
5209 /* enable a graceful server shutdown on an HTTP 404 response */
5210 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005211 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5212 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005213 }
Willy Tarreauef781042010-01-27 11:53:01 +01005214 else if (strcmp(args[1], "send-state") == 0) {
5215 /* enable emission of the apparent state of a server in HTTP checks */
5216 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005217 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5218 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005219 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005220 else if (strcmp(args[1], "expect") == 0) {
5221 const char *ptr_arg;
5222 int cur_arg;
5223
5224 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5225 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
5228 }
5229
5230 cur_arg = 2;
5231 /* consider exclamation marks, sole or at the beginning of a word */
5232 while (*(ptr_arg = args[cur_arg])) {
5233 while (*ptr_arg == '!') {
5234 curproxy->options2 ^= PR_O2_EXP_INV;
5235 ptr_arg++;
5236 }
5237 if (*ptr_arg)
5238 break;
5239 cur_arg++;
5240 }
5241 /* now ptr_arg points to the beginning of a word past any possible
5242 * exclamation mark, and cur_arg is the argument which holds this word.
5243 */
5244 if (strcmp(ptr_arg, "status") == 0) {
5245 if (!*(args[cur_arg + 1])) {
5246 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5247 file, linenum, args[0], args[1], ptr_arg);
5248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005252 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005253 curproxy->expect_str = strdup(args[cur_arg + 1]);
5254 }
5255 else if (strcmp(ptr_arg, "string") == 0) {
5256 if (!*(args[cur_arg + 1])) {
5257 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5258 file, linenum, args[0], args[1], ptr_arg);
5259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261 }
5262 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005263 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005264 curproxy->expect_str = strdup(args[cur_arg + 1]);
5265 }
5266 else if (strcmp(ptr_arg, "rstatus") == 0) {
5267 if (!*(args[cur_arg + 1])) {
5268 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5269 file, linenum, args[0], args[1], ptr_arg);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272 }
5273 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005274 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005275 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005276 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005277 free(curproxy->expect_regex);
5278 curproxy->expect_regex = NULL;
5279 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005280 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005281 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5282 error = NULL;
5283 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5284 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5285 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5286 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
5289 }
5290 }
5291 else if (strcmp(ptr_arg, "rstring") == 0) {
5292 if (!*(args[cur_arg + 1])) {
5293 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5294 file, linenum, args[0], args[1], ptr_arg);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005299 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005300 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005301 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005302 free(curproxy->expect_regex);
5303 curproxy->expect_regex = NULL;
5304 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005305 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005306 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5307 error = NULL;
5308 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5309 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5310 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5311 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315 }
5316 else {
5317 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5318 file, linenum, args[0], args[1], ptr_arg);
5319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
5321 }
5322 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005323 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005324 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 +02005325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005327 }
5328 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005329 else if (!strcmp(args[0], "tcp-check")) {
5330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5331 err_code |= ERR_WARN;
5332
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005333 if (strcmp(args[1], "comment") == 0) {
5334 int cur_arg;
5335 struct tcpcheck_rule *tcpcheck;
5336
5337 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005338 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005339 tcpcheck->action = TCPCHK_ACT_COMMENT;
5340
5341 if (!*args[cur_arg + 1]) {
5342 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5343 file, linenum, args[cur_arg]);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347
5348 tcpcheck->comment = strdup(args[cur_arg + 1]);
5349
5350 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005351 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5352 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005353 }
5354 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005355 const char *ptr_arg;
5356 int cur_arg;
5357 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005358
5359 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005360 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5361 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5362 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5363 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5364 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005365
Willy Tarreau5581c272015-05-13 12:24:53 +02005366 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5367 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5368 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5369 file, linenum);
5370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005372 }
5373
5374 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005375 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005376 tcpcheck->action = TCPCHK_ACT_CONNECT;
5377
5378 /* parsing each parameters to fill up the rule */
5379 while (*(ptr_arg = args[cur_arg])) {
5380 /* tcp port */
5381 if (strcmp(args[cur_arg], "port") == 0) {
5382 if ( (atol(args[cur_arg + 1]) > 65535) ||
5383 (atol(args[cur_arg + 1]) < 1) ){
5384 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5385 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
5388 }
5389 tcpcheck->port = atol(args[cur_arg + 1]);
5390 cur_arg += 2;
5391 }
5392 /* send proxy protocol */
5393 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5394 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5395 cur_arg++;
5396 }
5397#ifdef USE_OPENSSL
5398 else if (strcmp(args[cur_arg], "ssl") == 0) {
5399 curproxy->options |= PR_O_TCPCHK_SSL;
5400 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5401 cur_arg++;
5402 }
5403#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005404 /* comment for this tcpcheck line */
5405 else if (strcmp(args[cur_arg], "comment") == 0) {
5406 if (!*args[cur_arg + 1]) {
5407 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5408 file, linenum, args[cur_arg]);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412 tcpcheck->comment = strdup(args[cur_arg + 1]);
5413 cur_arg += 2;
5414 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005415 else {
5416#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005417 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 +01005418#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005419 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 +01005420#endif /* USE_OPENSSL */
5421 file, linenum, args[0], args[1], args[cur_arg]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425
5426 }
5427
5428 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5429 }
5430 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005431 if (! *(args[2]) ) {
5432 /* SEND string expected */
5433 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5434 file, linenum, args[0], args[1], args[2]);
5435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
5437 } else {
5438 struct tcpcheck_rule *tcpcheck;
5439
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005440 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005441
5442 tcpcheck->action = TCPCHK_ACT_SEND;
5443 tcpcheck->string_len = strlen(args[2]);
5444 tcpcheck->string = strdup(args[2]);
5445 tcpcheck->expect_regex = NULL;
5446
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005447 /* comment for this tcpcheck line */
5448 if (strcmp(args[3], "comment") == 0) {
5449 if (!*args[4]) {
5450 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5451 file, linenum, args[3]);
5452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
5454 }
5455 tcpcheck->comment = strdup(args[4]);
5456 }
5457
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005458 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5459 }
5460 }
5461 else if (strcmp(args[1], "send-binary") == 0) {
5462 if (! *(args[2]) ) {
5463 /* SEND binary string expected */
5464 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5465 file, linenum, args[0], args[1], args[2]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 } else {
5469 struct tcpcheck_rule *tcpcheck;
5470 char *err = NULL;
5471
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005472 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005473
5474 tcpcheck->action = TCPCHK_ACT_SEND;
5475 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5476 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5477 file, linenum, args[0], args[1], args[2], err);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
5481 tcpcheck->expect_regex = NULL;
5482
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005483 /* comment for this tcpcheck line */
5484 if (strcmp(args[3], "comment") == 0) {
5485 if (!*args[4]) {
5486 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5487 file, linenum, args[3]);
5488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
5490 }
5491 tcpcheck->comment = strdup(args[4]);
5492 }
5493
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005494 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5495 }
5496 }
5497 else if (strcmp(args[1], "expect") == 0) {
5498 const char *ptr_arg;
5499 int cur_arg;
5500 int inverse = 0;
5501
5502 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5503 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5504 err_code |= ERR_ALERT | ERR_FATAL;
5505 goto out;
5506 }
5507
5508 cur_arg = 2;
5509 /* consider exclamation marks, sole or at the beginning of a word */
5510 while (*(ptr_arg = args[cur_arg])) {
5511 while (*ptr_arg == '!') {
5512 inverse = !inverse;
5513 ptr_arg++;
5514 }
5515 if (*ptr_arg)
5516 break;
5517 cur_arg++;
5518 }
5519 /* now ptr_arg points to the beginning of a word past any possible
5520 * exclamation mark, and cur_arg is the argument which holds this word.
5521 */
5522 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005523 struct tcpcheck_rule *tcpcheck;
5524 char *err = NULL;
5525
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005526 if (!*(args[cur_arg + 1])) {
5527 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5528 file, linenum, args[0], args[1], ptr_arg);
5529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
5531 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005532
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005533 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005534
5535 tcpcheck->action = TCPCHK_ACT_EXPECT;
5536 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5537 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5538 file, linenum, args[0], args[1], args[2], err);
5539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
5542 tcpcheck->expect_regex = NULL;
5543 tcpcheck->inverse = inverse;
5544
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005545 /* tcpcheck comment */
5546 cur_arg += 2;
5547 if (strcmp(args[cur_arg], "comment") == 0) {
5548 if (!*args[cur_arg + 1]) {
5549 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5550 file, linenum, args[cur_arg + 1]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554 tcpcheck->comment = strdup(args[cur_arg + 1]);
5555 }
5556
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005557 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5558 }
5559 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005560 struct tcpcheck_rule *tcpcheck;
5561
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005562 if (!*(args[cur_arg + 1])) {
5563 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5564 file, linenum, args[0], args[1], ptr_arg);
5565 err_code |= ERR_ALERT | ERR_FATAL;
5566 goto out;
5567 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005568
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005569 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005570
5571 tcpcheck->action = TCPCHK_ACT_EXPECT;
5572 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5573 tcpcheck->string = strdup(args[cur_arg + 1]);
5574 tcpcheck->expect_regex = NULL;
5575 tcpcheck->inverse = inverse;
5576
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005577 /* tcpcheck comment */
5578 cur_arg += 2;
5579 if (strcmp(args[cur_arg], "comment") == 0) {
5580 if (!*args[cur_arg + 1]) {
5581 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5582 file, linenum, args[cur_arg + 1]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
5586 tcpcheck->comment = strdup(args[cur_arg + 1]);
5587 }
5588
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005589 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5590 }
5591 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005592 struct tcpcheck_rule *tcpcheck;
5593
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005594 if (!*(args[cur_arg + 1])) {
5595 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5596 file, linenum, args[0], args[1], ptr_arg);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005600
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005601 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005602
5603 tcpcheck->action = TCPCHK_ACT_EXPECT;
5604 tcpcheck->string_len = 0;
5605 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005606 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5607 error = NULL;
5608 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5609 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5610 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5611 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615 tcpcheck->inverse = inverse;
5616
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005617 /* tcpcheck comment */
5618 cur_arg += 2;
5619 if (strcmp(args[cur_arg], "comment") == 0) {
5620 if (!*args[cur_arg + 1]) {
5621 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5622 file, linenum, args[cur_arg + 1]);
5623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
5626 tcpcheck->comment = strdup(args[cur_arg + 1]);
5627 }
5628
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005629 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5630 }
5631 else {
5632 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5633 file, linenum, args[0], args[1], ptr_arg);
5634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
5636 }
5637 }
5638 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005639 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
5642 }
5643 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005644 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005645 if (curproxy == &defproxy) {
5646 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005649 }
5650
Willy Tarreaub80c2302007-11-30 20:51:32 +01005651 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005652 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005653
5654 if (strcmp(args[1], "fail") == 0) {
5655 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005656 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005657 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5658 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005661 }
5662
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005663 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5664 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5665 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005666 err_code |= ERR_ALERT | ERR_FATAL;
5667 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005668 }
5669 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5670 }
5671 else {
5672 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005675 }
5676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677#ifdef TPROXY
5678 else if (!strcmp(args[0], "transparent")) {
5679 /* enable transparent proxy connections */
5680 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005681 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
5684#endif
5685 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005686 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005688
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 if (*(args[1]) == 0) {
5690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 }
5694 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005695 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005698 else if (!strcmp(args[0], "backlog")) { /* backlog */
5699 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005700 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005701
5702 if (*(args[1]) == 0) {
5703 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005706 }
5707 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5709 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005710 }
Willy Tarreau86034312006-12-29 00:10:33 +01005711 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005712 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005713 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005714
Willy Tarreau86034312006-12-29 00:10:33 +01005715 if (*(args[1]) == 0) {
5716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005719 }
5720 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005721 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5722 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5725 if (*(args[1]) == 0) {
5726 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005730 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5731 if (err) {
5732 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5733 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005736 }
5737 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005738 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 }
5741 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005742 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005743 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005744 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005745
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 if (curproxy == &defproxy) {
5747 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005751 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005752 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005753
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005754 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005755 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005756 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005757 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005758 goto out;
5759 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005760
5761 proto = protocol_by_family(sk->ss_family);
5762 if (!proto || !proto->connect) {
5763 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5764 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005765 err_code |= ERR_ALERT | ERR_FATAL;
5766 goto out;
5767 }
5768
5769 if (port1 != port2) {
5770 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5771 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005775
5776 if (!port1) {
5777 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5778 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005779 err_code |= ERR_ALERT | ERR_FATAL;
5780 goto out;
5781 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005782
William Lallemanddf1425a2015-04-28 20:17:49 +02005783 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5784 goto out;
5785
Willy Tarreaud5191e72010-02-09 20:50:45 +01005786 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005787 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 }
5789 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005791 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005792
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005793 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5794 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005797 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005799 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005800 /**
5801 * The syntax for hash-type config element is
5802 * hash-type {map-based|consistent} [[<algo>] avalanche]
5803 *
5804 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5805 */
5806 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005807
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5809 err_code |= ERR_WARN;
5810
5811 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005812 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5813 }
5814 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005815 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5816 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005817 else if (strcmp(args[1], "avalanche") == 0) {
5818 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]);
5819 err_code |= ERR_ALERT | ERR_FATAL;
5820 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005821 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005822 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005823 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005824 err_code |= ERR_ALERT | ERR_FATAL;
5825 goto out;
5826 }
Bhaskar98634f02013-10-29 23:30:51 -04005827
5828 /* set the hash function to use */
5829 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005830 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005831 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005832
5833 /* if consistent with no argument, then avalanche modifier is also applied */
5834 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5835 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005836 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005837 /* set the hash function */
5838 if (!strcmp(args[2], "sdbm")) {
5839 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5840 }
5841 else if (!strcmp(args[2], "djb2")) {
5842 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005843 }
5844 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005845 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005846 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005847 else if (!strcmp(args[2], "crc32")) {
5848 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5849 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005850 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005851 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 -05005852 err_code |= ERR_ALERT | ERR_FATAL;
5853 goto out;
5854 }
5855
5856 /* set the hash modifier */
5857 if (!strcmp(args[3], "avalanche")) {
5858 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5859 }
5860 else if (*args[3]) {
5861 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005865 }
William Lallemanda73203e2012-03-12 12:48:57 +01005866 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005867 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5868 if (*(args[1]) == 0) {
5869 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5870 err_code |= ERR_ALERT | ERR_FATAL;
5871 goto out;
5872 }
5873 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5874 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5875 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
5878 }
5879 }
William Lallemanda73203e2012-03-12 12:48:57 +01005880 else if (strcmp(args[0], "unique-id-format") == 0) {
5881 if (!*(args[1])) {
5882 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
5885 }
William Lallemand3203ff42012-11-11 17:30:56 +01005886 if (*(args[2])) {
5887 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5888 err_code |= ERR_ALERT | ERR_FATAL;
5889 goto out;
5890 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005891 free(curproxy->conf.uniqueid_format_string);
5892 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005893
Willy Tarreau62a61232013-04-12 18:13:46 +02005894 free(curproxy->conf.uif_file);
5895 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5896 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005897 }
William Lallemanda73203e2012-03-12 12:48:57 +01005898
5899 else if (strcmp(args[0], "unique-id-header") == 0) {
5900 if (!*(args[1])) {
5901 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5902 err_code |= ERR_ALERT | ERR_FATAL;
5903 goto out;
5904 }
5905 free(curproxy->header_unique_id);
5906 curproxy->header_unique_id = strdup(args[1]);
5907 }
5908
William Lallemand723b73a2012-02-08 16:37:49 +01005909 else if (strcmp(args[0], "log-format") == 0) {
5910 if (!*(args[1])) {
5911 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
5914 }
William Lallemand3203ff42012-11-11 17:30:56 +01005915 if (*(args[2])) {
5916 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
5919 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005920 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5921 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005922
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005923 if (curproxy->conf.logformat_string == default_http_log_format)
5924 oldlogformat = "option httplog";
5925 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5926 oldlogformat = "option tcplog";
5927 else if (curproxy->conf.logformat_string == clf_http_log_format)
5928 oldlogformat = "option httplog clf";
5929 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5930 file, linenum, oldlogformat);
5931 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005932 if (curproxy->conf.logformat_string != default_http_log_format &&
5933 curproxy->conf.logformat_string != default_tcp_log_format &&
5934 curproxy->conf.logformat_string != clf_http_log_format)
5935 free(curproxy->conf.logformat_string);
5936 curproxy->conf.logformat_string = strdup(args[1]);
5937
5938 free(curproxy->conf.lfs_file);
5939 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5940 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005941
5942 /* get a chance to improve log-format error reporting by
5943 * reporting the correct line-number when possible.
5944 */
5945 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5946 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5947 file, linenum, curproxy->id);
5948 err_code |= ERR_WARN;
5949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005951 else if (!strcmp(args[0], "log-format-sd")) {
5952 if (!*(args[1])) {
5953 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
5956 }
5957 if (*(args[2])) {
5958 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5959 err_code |= ERR_ALERT | ERR_FATAL;
5960 goto out;
5961 }
5962
5963 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5964 free(curproxy->conf.logformat_sd_string);
5965 curproxy->conf.logformat_sd_string = strdup(args[1]);
5966
5967 free(curproxy->conf.lfsd_file);
5968 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5969 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5970
5971 /* get a chance to improve log-format-sd error reporting by
5972 * reporting the correct line-number when possible.
5973 */
5974 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5975 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5976 file, linenum, curproxy->id);
5977 err_code |= ERR_WARN;
5978 }
5979 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005980 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5981 if (*(args[1]) == 0) {
5982 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5983 err_code |= ERR_ALERT | ERR_FATAL;
5984 goto out;
5985 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005986 chunk_destroy(&curproxy->log_tag);
5987 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005988 }
William Lallemand0f99e342011-10-12 17:50:54 +02005989 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5990 /* delete previous herited or defined syslog servers */
5991 struct logsrv *back;
5992
5993 if (*(args[1]) != 0) {
5994 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5995 err_code |= ERR_ALERT | ERR_FATAL;
5996 goto out;
5997 }
5998
William Lallemand723b73a2012-02-08 16:37:49 +01005999 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6000 LIST_DEL(&tmplogsrv->list);
6001 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006002 }
6003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006004 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006005 struct logsrv *logsrv;
6006
Willy Tarreaubaaee002006-06-26 02:48:02 +02006007 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006008 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006009 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006010 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006011 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006012 LIST_INIT(&node->list);
6013 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 }
6016 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006017 struct sockaddr_storage *sk;
6018 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006019 int arg = 0;
6020 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006021
Vincent Bernat02779b62016-04-03 13:48:43 +02006022 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023
Willy Tarreau18324f52014-06-27 18:10:07 +02006024 /* just after the address, a length may be specified */
6025 if (strcmp(args[arg+2], "len") == 0) {
6026 len = atoi(args[arg+3]);
6027 if (len < 80 || len > 65535) {
6028 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6029 file, linenum, args[arg+3]);
6030 err_code |= ERR_ALERT | ERR_FATAL;
6031 goto out;
6032 }
6033 logsrv->maxlen = len;
6034
6035 /* skip these two args */
6036 arg += 2;
6037 }
6038 else
6039 logsrv->maxlen = MAX_SYSLOG_LEN;
6040
6041 if (logsrv->maxlen > global.max_syslog_len) {
6042 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006043 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6044 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6045 logline = my_realloc2(logline, global.max_syslog_len + 1);
6046 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006047 }
6048
Dragan Dosen1322d092015-09-22 16:05:32 +02006049 /* after the length, a format may be specified */
6050 if (strcmp(args[arg+2], "format") == 0) {
6051 logsrv->format = get_log_format(args[arg+3]);
6052 if (logsrv->format < 0) {
6053 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6054 err_code |= ERR_ALERT | ERR_FATAL;
6055 goto out;
6056 }
6057
6058 /* skip these two args */
6059 arg += 2;
6060 }
6061
William Lallemanddf1425a2015-04-28 20:17:49 +02006062 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6063 goto out;
6064
Willy Tarreau18324f52014-06-27 18:10:07 +02006065 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006066 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006067 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070
Willy Tarreaubaaee002006-06-26 02:48:02 +02006071 }
6072
William Lallemand0f99e342011-10-12 17:50:54 +02006073 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006074 if (*(args[arg+3])) {
6075 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006076 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006077 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006078 err_code |= ERR_ALERT | ERR_FATAL;
6079 goto out;
6080
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081 }
6082 }
6083
William Lallemand0f99e342011-10-12 17:50:54 +02006084 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006085 if (*(args[arg+4])) {
6086 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006087 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006088 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006089 err_code |= ERR_ALERT | ERR_FATAL;
6090 goto out;
6091
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006092 }
6093 }
6094
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006095 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006096 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006097 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006098 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006099 goto out;
6100 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006101
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006102 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006103
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006104 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006105 if (port1 != port2) {
6106 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6107 file, linenum, args[0], args[1]);
6108 err_code |= ERR_ALERT | ERR_FATAL;
6109 goto out;
6110 }
6111
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006112 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006113 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006114 }
William Lallemand0f99e342011-10-12 17:50:54 +02006115
6116 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006117 }
6118 else {
6119 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6120 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006121 err_code |= ERR_ALERT | ERR_FATAL;
6122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006123 }
6124 }
6125 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006126 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006127 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006128 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006129 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006130
Willy Tarreau977b8e42006-12-29 14:19:17 +01006131 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006132 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006133
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006135 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6136 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006137 err_code |= ERR_ALERT | ERR_FATAL;
6138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006140
6141 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006142 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6143 free(curproxy->conn_src.iface_name);
6144 curproxy->conn_src.iface_name = NULL;
6145 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006146
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006147 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006148 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006149 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006150 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006151 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006152 goto out;
6153 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006154
6155 proto = protocol_by_family(sk->ss_family);
6156 if (!proto || !proto->connect) {
6157 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006158 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006159 err_code |= ERR_ALERT | ERR_FATAL;
6160 goto out;
6161 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006162
6163 if (port1 != port2) {
6164 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6165 file, linenum, args[0], args[1]);
6166 err_code |= ERR_ALERT | ERR_FATAL;
6167 goto out;
6168 }
6169
Willy Tarreauef9a3602012-12-08 22:29:20 +01006170 curproxy->conn_src.source_addr = *sk;
6171 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006172
6173 cur_arg = 2;
6174 while (*(args[cur_arg])) {
6175 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006176#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006177 if (!*args[cur_arg + 1]) {
6178 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6179 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006180 err_code |= ERR_ALERT | ERR_FATAL;
6181 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006182 }
6183
6184 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006185 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6186 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006187 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006188 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6189 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006190 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6191 char *name, *end;
6192
6193 name = args[cur_arg+1] + 7;
6194 while (isspace(*name))
6195 name++;
6196
6197 end = name;
6198 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6199 end++;
6200
Willy Tarreauef9a3602012-12-08 22:29:20 +01006201 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6202 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6203 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6204 curproxy->conn_src.bind_hdr_len = end - name;
6205 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6206 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6207 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006208
6209 /* now look for an occurrence number */
6210 while (isspace(*end))
6211 end++;
6212 if (*end == ',') {
6213 end++;
6214 name = end;
6215 if (*end == '-')
6216 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006217 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006218 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006219 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006220 }
6221
Willy Tarreauef9a3602012-12-08 22:29:20 +01006222 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006223 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6224 " occurrences values smaller than %d.\n",
6225 file, linenum, MAX_HDR_HISTORY);
6226 err_code |= ERR_ALERT | ERR_FATAL;
6227 goto out;
6228 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006229 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006230 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006231
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006232 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006233 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006234 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006235 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006236 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006237 goto out;
6238 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006239
6240 proto = protocol_by_family(sk->ss_family);
6241 if (!proto || !proto->connect) {
6242 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6243 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006244 err_code |= ERR_ALERT | ERR_FATAL;
6245 goto out;
6246 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006247
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006248 if (port1 != port2) {
6249 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6250 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006251 err_code |= ERR_ALERT | ERR_FATAL;
6252 goto out;
6253 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006254 curproxy->conn_src.tproxy_addr = *sk;
6255 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006256 }
6257 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006258#else /* no TPROXY support */
6259 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006260 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006261 err_code |= ERR_ALERT | ERR_FATAL;
6262 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006263#endif
6264 cur_arg += 2;
6265 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006266 }
6267
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006268 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6269#ifdef SO_BINDTODEVICE
6270 if (!*args[cur_arg + 1]) {
6271 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6272 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006273 err_code |= ERR_ALERT | ERR_FATAL;
6274 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006275 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006276 free(curproxy->conn_src.iface_name);
6277 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6278 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006279 global.last_checks |= LSTCHK_NETADM;
6280#else
6281 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6282 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006283 err_code |= ERR_ALERT | ERR_FATAL;
6284 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006285#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006286 cur_arg += 2;
6287 continue;
6288 }
6289 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006290 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006291 err_code |= ERR_ALERT | ERR_FATAL;
6292 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006294 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006295 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6296 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6297 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006298 err_code |= ERR_ALERT | ERR_FATAL;
6299 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006302 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006303 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6304 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006305 err_code |= ERR_ALERT | ERR_FATAL;
6306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006307 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006308
6309 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006310 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006311 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006312 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 }
6315 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006316 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006317 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006318 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006319 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 }
6322 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006323 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006324 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006325 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006326 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 }
6329 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006330 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006331 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006332 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006333 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 }
6336 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006337 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006338 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006339 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006340 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006343 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006345 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006346 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006347 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006348 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006354 err_code |= ERR_ALERT | ERR_FATAL;
6355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357
6358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006359 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006360 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 }
6364 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006366 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
6371 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006373 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 }
6378 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006380 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006381 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006382 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 }
6385 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006386 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006387 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006388 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006389 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006392 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006394 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006395 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006396 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006397 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006400 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006401
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 if (curproxy == &defproxy) {
6403 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006404 err_code |= ERR_ALERT | ERR_FATAL;
6405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006407 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006408 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409
Willy Tarreaubaaee002006-06-26 02:48:02 +02006410 if (*(args[1]) == 0) {
6411 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006412 err_code |= ERR_ALERT | ERR_FATAL;
6413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006415
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006416 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006417 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6418 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6419 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006420 err_code |= ERR_ALERT | ERR_FATAL;
6421 goto out;
6422 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006423 err_code |= warnif_cond_conflicts(cond,
6424 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6425 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006426 }
6427 else if (*args[2]) {
6428 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6429 file, linenum, args[0], args[2]);
6430 err_code |= ERR_ALERT | ERR_FATAL;
6431 goto out;
6432 }
6433
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006434 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006435 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006436 wl->s = strdup(args[1]);
6437 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006438 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439 }
6440 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006441 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6443 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006444 err_code |= ERR_ALERT | ERR_FATAL;
6445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006447
Willy Tarreauade5ec42010-01-28 19:33:49 +01006448 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006449 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006450 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006451 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 }
6454 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006455 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006456 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006457 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 }
6461 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006463 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006464 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 }
6468 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006469 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6471 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006472 err_code |= ERR_ALERT | ERR_FATAL;
6473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 }
6475
Willy Tarreauade5ec42010-01-28 19:33:49 +01006476 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006477 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006478 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006479 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 }
6482 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006483 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006484 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006485 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006486 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 }
6489 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006491 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006492 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006493 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 }
6496 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006497 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006498
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 if (curproxy == &defproxy) {
6500 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006501 err_code |= ERR_ALERT | ERR_FATAL;
6502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006504 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006505 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506
Willy Tarreaubaaee002006-06-26 02:48:02 +02006507 if (*(args[1]) == 0) {
6508 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006509 err_code |= ERR_ALERT | ERR_FATAL;
6510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006513 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006514 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6515 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6516 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006517 err_code |= ERR_ALERT | ERR_FATAL;
6518 goto out;
6519 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006520 err_code |= warnif_cond_conflicts(cond,
6521 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6522 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006523 }
6524 else if (*args[2]) {
6525 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6526 file, linenum, args[0], args[2]);
6527 err_code |= ERR_ALERT | ERR_FATAL;
6528 goto out;
6529 }
6530
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006531 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006532 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006533 wl->s = strdup(args[1]);
6534 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006535 }
6536 else if (!strcmp(args[0], "errorloc") ||
6537 !strcmp(args[0], "errorloc302") ||
6538 !strcmp(args[0], "errorloc303")) { /* error location */
6539 int errnum, errlen;
6540 char *err;
6541
Willy Tarreau977b8e42006-12-29 14:19:17 +01006542 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006543 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006544
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006546 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006547 err_code |= ERR_ALERT | ERR_FATAL;
6548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 }
6550
6551 errnum = atol(args[1]);
6552 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006553 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6554 err = malloc(errlen);
6555 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006557 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6558 err = malloc(errlen);
6559 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006560 }
6561
Willy Tarreau0f772532006-12-23 20:51:41 +01006562 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6563 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006564 chunk_destroy(&curproxy->errmsg[rc]);
6565 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006566 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006569
6570 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006571 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6572 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006573 free(err);
6574 }
6575 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006576 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6577 int errnum, errlen, fd;
6578 char *err;
6579 struct stat stat;
6580
6581 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006582 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006583
6584 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006585 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006586 err_code |= ERR_ALERT | ERR_FATAL;
6587 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006588 }
6589
6590 fd = open(args[2], O_RDONLY);
6591 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6592 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6593 file, linenum, args[2], args[1]);
6594 if (fd >= 0)
6595 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006596 err_code |= ERR_ALERT | ERR_FATAL;
6597 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006598 }
6599
Willy Tarreau27a674e2009-08-17 07:23:33 +02006600 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006601 errlen = stat.st_size;
6602 } else {
6603 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006604 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006605 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006606 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006607 }
6608
6609 err = malloc(errlen); /* malloc() must succeed during parsing */
6610 errnum = read(fd, err, errlen);
6611 if (errnum != errlen) {
6612 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6613 file, linenum, args[2], args[1]);
6614 close(fd);
6615 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006616 err_code |= ERR_ALERT | ERR_FATAL;
6617 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006618 }
6619 close(fd);
6620
6621 errnum = atol(args[1]);
6622 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6623 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006624 chunk_destroy(&curproxy->errmsg[rc]);
6625 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006626 break;
6627 }
6628 }
6629
6630 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006631 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6632 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006633 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006634 free(err);
6635 }
6636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006637 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006638 struct cfg_kw_list *kwl;
6639 int index;
6640
6641 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6642 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6643 if (kwl->kw[index].section != CFG_LISTEN)
6644 continue;
6645 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6646 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006647 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006648 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006649 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006650 err_code |= ERR_ALERT | ERR_FATAL;
6651 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006652 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006653 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006654 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006655 err_code |= ERR_WARN;
6656 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006657 }
Willy Tarreau93893792009-07-23 13:19:11 +02006658 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006659 }
6660 }
6661 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006662
Willy Tarreau6daf3432008-01-22 16:44:08 +01006663 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006664 err_code |= ERR_ALERT | ERR_FATAL;
6665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006666 }
Willy Tarreau93893792009-07-23 13:19:11 +02006667 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006668 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006669 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006670}
6671
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006672int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006673cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6674{
6675#ifdef CONFIG_HAP_NS
6676 const char *err;
6677 const char *item = args[0];
6678
6679 if (!strcmp(item, "namespace_list")) {
6680 return 0;
6681 }
6682 else if (!strcmp(item, "namespace")) {
6683 size_t idx = 1;
6684 const char *current;
6685 while (*(current = args[idx++])) {
6686 err = invalid_char(current);
6687 if (err) {
6688 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6689 file, linenum, *err, item, current);
6690 return ERR_ALERT | ERR_FATAL;
6691 }
6692
6693 if (netns_store_lookup(current, strlen(current))) {
6694 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6695 file, linenum, current);
6696 return ERR_ALERT | ERR_FATAL;
6697 }
6698 if (!netns_store_insert(current)) {
6699 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6700 file, linenum, current);
6701 return ERR_ALERT | ERR_FATAL;
6702 }
6703 }
6704 }
6705
6706 return 0;
6707#else
6708 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6709 file, linenum);
6710 return ERR_ALERT | ERR_FATAL;
6711#endif
6712}
6713
6714int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006715cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6716{
6717
6718 int err_code = 0;
6719 const char *err;
6720
6721 if (!strcmp(args[0], "userlist")) { /* new userlist */
6722 struct userlist *newul;
6723
6724 if (!*args[1]) {
6725 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6726 file, linenum, args[0]);
6727 err_code |= ERR_ALERT | ERR_FATAL;
6728 goto out;
6729 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006730 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6731 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732
6733 err = invalid_char(args[1]);
6734 if (err) {
6735 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6736 file, linenum, *err, args[0], args[1]);
6737 err_code |= ERR_ALERT | ERR_FATAL;
6738 goto out;
6739 }
6740
6741 for (newul = userlist; newul; newul = newul->next)
6742 if (!strcmp(newul->name, args[1])) {
6743 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6744 file, linenum, args[1]);
6745 err_code |= ERR_WARN;
6746 goto out;
6747 }
6748
Vincent Bernat02779b62016-04-03 13:48:43 +02006749 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006750 if (!newul) {
6751 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6752 err_code |= ERR_ALERT | ERR_ABORT;
6753 goto out;
6754 }
6755
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006756 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006757 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006758 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6759 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006760 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006761 goto out;
6762 }
6763
6764 newul->next = userlist;
6765 userlist = newul;
6766
6767 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006768 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006769 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006770 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006771
6772 if (!*args[1]) {
6773 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6774 file, linenum, args[0]);
6775 err_code |= ERR_ALERT | ERR_FATAL;
6776 goto out;
6777 }
6778
6779 err = invalid_char(args[1]);
6780 if (err) {
6781 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6782 file, linenum, *err, args[0], args[1]);
6783 err_code |= ERR_ALERT | ERR_FATAL;
6784 goto out;
6785 }
6786
William Lallemand4ac9f542015-05-28 18:03:51 +02006787 if (!userlist)
6788 goto out;
6789
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006790 for (ag = userlist->groups; ag; ag = ag->next)
6791 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6793 file, linenum, args[1], userlist->name);
6794 err_code |= ERR_ALERT;
6795 goto out;
6796 }
6797
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006798 ag = calloc(1, sizeof(*ag));
6799 if (!ag) {
6800 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6801 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802 goto out;
6803 }
6804
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006805 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006806 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006807 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6808 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006809 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006810 goto out;
6811 }
6812
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813 cur_arg = 2;
6814
6815 while (*args[cur_arg]) {
6816 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006817 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006818 cur_arg += 2;
6819 continue;
6820 } else {
6821 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6822 file, linenum, args[0]);
6823 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006824 free(ag->groupusers);
6825 free(ag->name);
6826 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006827 goto out;
6828 }
6829 }
6830
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006831 ag->next = userlist->groups;
6832 userlist->groups = ag;
6833
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 } else if (!strcmp(args[0], "user")) { /* new user */
6835 struct auth_users *newuser;
6836 int cur_arg;
6837
6838 if (!*args[1]) {
6839 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6840 file, linenum, args[0]);
6841 err_code |= ERR_ALERT | ERR_FATAL;
6842 goto out;
6843 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006844 if (!userlist)
6845 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006846
6847 for (newuser = userlist->users; newuser; newuser = newuser->next)
6848 if (!strcmp(newuser->user, args[1])) {
6849 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6850 file, linenum, args[1], userlist->name);
6851 err_code |= ERR_ALERT;
6852 goto out;
6853 }
6854
Vincent Bernat02779b62016-04-03 13:48:43 +02006855 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006856 if (!newuser) {
6857 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6858 err_code |= ERR_ALERT | ERR_ABORT;
6859 goto out;
6860 }
6861
6862 newuser->user = strdup(args[1]);
6863
6864 newuser->next = userlist->users;
6865 userlist->users = newuser;
6866
6867 cur_arg = 2;
6868
6869 while (*args[cur_arg]) {
6870 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006871#ifdef CONFIG_HAP_CRYPT
6872 if (!crypt("", args[cur_arg + 1])) {
6873 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6874 file, linenum, newuser->user);
6875 err_code |= ERR_ALERT | ERR_FATAL;
6876 goto out;
6877 }
6878#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006879 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6880 file, linenum);
6881 err_code |= ERR_ALERT;
6882#endif
6883 newuser->pass = strdup(args[cur_arg + 1]);
6884 cur_arg += 2;
6885 continue;
6886 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6887 newuser->pass = strdup(args[cur_arg + 1]);
6888 newuser->flags |= AU_O_INSECURE;
6889 cur_arg += 2;
6890 continue;
6891 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006892 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006893 cur_arg += 2;
6894 continue;
6895 } else {
6896 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6897 file, linenum, args[0]);
6898 err_code |= ERR_ALERT | ERR_FATAL;
6899 goto out;
6900 }
6901 }
6902 } else {
6903 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6904 err_code |= ERR_ALERT | ERR_FATAL;
6905 }
6906
6907out:
6908 return err_code;
6909}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006910
Christopher Faulet79bdef32016-11-04 22:36:15 +01006911int
6912cfg_parse_scope(const char *file, int linenum, char *line)
6913{
6914 char *beg, *end, *scope = NULL;
6915 int err_code = 0;
6916 const char *err;
6917
6918 beg = line + 1;
6919 end = strchr(beg, ']');
6920
6921 /* Detect end of scope declaration */
6922 if (!end || end == beg) {
6923 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6924 file, linenum);
6925 err_code |= ERR_ALERT | ERR_FATAL;
6926 goto out;
6927 }
6928
6929 /* Get scope name and check its validity */
6930 scope = my_strndup(beg, end-beg);
6931 err = invalid_char(scope);
6932 if (err) {
6933 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6934 file, linenum, *err);
6935 err_code |= ERR_ALERT | ERR_ABORT;
6936 goto out;
6937 }
6938
6939 /* Be sure to have a scope declaration alone on its line */
6940 line = end+1;
6941 while (isspace((unsigned char)*line))
6942 line++;
6943 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6944 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6945 file, linenum, *line);
6946 err_code |= ERR_ALERT | ERR_ABORT;
6947 goto out;
6948 }
6949
6950 /* We have a valid scope declaration, save it */
6951 free(cfg_scope);
6952 cfg_scope = scope;
6953 scope = NULL;
6954
6955 out:
6956 free(scope);
6957 return err_code;
6958}
6959
Willy Tarreaubaaee002006-06-26 02:48:02 +02006960/*
6961 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006962 * Returns the error code, 0 if OK, or any combination of :
6963 * - ERR_ABORT: must abort ASAP
6964 * - ERR_FATAL: we can continue parsing but not start the service
6965 * - ERR_WARN: a warning has been emitted
6966 * - ERR_ALERT: an alert has been emitted
6967 * Only the two first ones can stop processing, the two others are just
6968 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006969 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006970int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006971{
William Lallemand64e84512015-05-12 14:25:37 +02006972 char *thisline;
6973 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006974 FILE *f;
6975 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006976 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006977 struct cfg_section *cs = NULL;
6978 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006979 int readbytes = 0;
6980
6981 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006982 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006983 return -1;
6984 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006985
David Carlier97880bb2016-04-08 10:35:26 +01006986 if ((f=fopen(file,"r")) == NULL) {
6987 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006988 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006990
William Lallemandb2f07452015-05-12 14:27:13 +02006991next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006992 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006993 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006994 char *end;
6995 char *args[MAX_LINE_ARGS + 1];
6996 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006997 int dquote = 0; /* double quote */
6998 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006999
Willy Tarreaubaaee002006-06-26 02:48:02 +02007000 linenum++;
7001
7002 end = line + strlen(line);
7003
William Lallemand64e84512015-05-12 14:25:37 +02007004 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007005 /* Check if we reached the limit and the last char is not \n.
7006 * Watch out for the last line without the terminating '\n'!
7007 */
William Lallemand64e84512015-05-12 14:25:37 +02007008 char *newline;
7009 int newlinesize = linesize * 2;
7010
7011 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7012 if (newline == NULL) {
7013 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7014 file, linenum);
7015 err_code |= ERR_ALERT | ERR_FATAL;
7016 continue;
7017 }
7018
7019 readbytes = linesize - 1;
7020 linesize = newlinesize;
7021 thisline = newline;
7022 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007023 }
7024
William Lallemand64e84512015-05-12 14:25:37 +02007025 readbytes = 0;
7026
Willy Tarreaubaaee002006-06-26 02:48:02 +02007027 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007028 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007029 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007030
Christopher Faulet79bdef32016-11-04 22:36:15 +01007031
7032 if (*line == '[') {/* This is the begining if a scope */
7033 err_code |= cfg_parse_scope(file, linenum, line);
7034 goto next_line;
7035 }
7036
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037 arg = 0;
7038 args[arg] = line;
7039
7040 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007041 if (*line == '"' && !squote) { /* double quote outside single quotes */
7042 if (dquote)
7043 dquote = 0;
7044 else
7045 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007046 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007047 end--;
7048 }
7049 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7050 if (squote)
7051 squote = 0;
7052 else
7053 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007054 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007055 end--;
7056 }
7057 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007058 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7059 * C equivalent value. Other combinations left unchanged (eg: \1).
7060 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007061 int skip = 0;
7062 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7063 *line = line[1];
7064 skip = 1;
7065 }
7066 else if (line[1] == 'r') {
7067 *line = '\r';
7068 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007070 else if (line[1] == 'n') {
7071 *line = '\n';
7072 skip = 1;
7073 }
7074 else if (line[1] == 't') {
7075 *line = '\t';
7076 skip = 1;
7077 }
7078 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007079 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 unsigned char hex1, hex2;
7081 hex1 = toupper(line[2]) - '0';
7082 hex2 = toupper(line[3]) - '0';
7083 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7084 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7085 *line = (hex1<<4) + hex2;
7086 skip = 3;
7087 }
7088 else {
7089 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007090 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007091 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007092 } else if (line[1] == '"') {
7093 *line = '"';
7094 skip = 1;
7095 } else if (line[1] == '\'') {
7096 *line = '\'';
7097 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007098 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7099 *line = '$';
7100 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 }
7102 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007103 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104 end -= skip;
7105 }
7106 line++;
7107 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007108 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109 /* end of string, end of loop */
7110 *line = 0;
7111 break;
7112 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007113 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007114 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007115 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007116 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007117 line++;
7118 args[++arg] = line;
7119 }
William Lallemandb2f07452015-05-12 14:27:13 +02007120 else if (dquote && *line == '$') {
7121 /* environment variables are evaluated inside double quotes */
7122 char *var_beg;
7123 char *var_end;
7124 char save_char;
7125 char *value;
7126 int val_len;
7127 int newlinesize;
7128 int braces = 0;
7129
7130 var_beg = line + 1;
7131 var_end = var_beg;
7132
7133 if (*var_beg == '{') {
7134 var_beg++;
7135 var_end++;
7136 braces = 1;
7137 }
7138
7139 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7140 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7141 err_code |= ERR_ALERT | ERR_FATAL;
7142 goto next_line; /* skip current line */
7143 }
7144
7145 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7146 var_end++;
7147
7148 save_char = *var_end;
7149 *var_end = '\0';
7150 value = getenv(var_beg);
7151 *var_end = save_char;
7152 val_len = value ? strlen(value) : 0;
7153
7154 if (braces) {
7155 if (*var_end == '}') {
7156 var_end++;
7157 braces = 0;
7158 } else {
7159 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7160 err_code |= ERR_ALERT | ERR_FATAL;
7161 goto next_line; /* skip current line */
7162 }
7163 }
7164
7165 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7166
7167 /* if not enough space in thisline */
7168 if (newlinesize > linesize) {
7169 char *newline;
7170
7171 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7172 if (newline == NULL) {
7173 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7174 err_code |= ERR_ALERT | ERR_FATAL;
7175 goto next_line; /* slip current line */
7176 }
7177 /* recompute pointers if realloc returns a new pointer */
7178 if (newline != thisline) {
7179 int i;
7180 int diff;
7181
7182 for (i = 0; i <= arg; i++) {
7183 diff = args[i] - thisline;
7184 args[i] = newline + diff;
7185 }
7186
7187 diff = var_end - thisline;
7188 var_end = newline + diff;
7189 diff = end - thisline;
7190 end = newline + diff;
7191 diff = line - thisline;
7192 line = newline + diff;
7193 thisline = newline;
7194 }
7195 linesize = newlinesize;
7196 }
7197
7198 /* insert value inside the line */
7199 memmove(line + val_len, var_end, end - var_end + 1);
7200 memcpy(line, value, val_len);
7201 end += val_len - (var_end - line);
7202 line += val_len;
7203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007204 else {
7205 line++;
7206 }
7207 }
William Lallemandb2f07452015-05-12 14:27:13 +02007208
William Lallemandf9873ba2015-05-05 17:37:14 +02007209 if (dquote) {
7210 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7211 err_code |= ERR_ALERT | ERR_FATAL;
7212 }
7213
7214 if (squote) {
7215 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7216 err_code |= ERR_ALERT | ERR_FATAL;
7217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007218
7219 /* empty line */
7220 if (!**args)
7221 continue;
7222
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007223 if (*line) {
7224 /* we had to stop due to too many args.
7225 * Let's terminate the string, print the offending part then cut the
7226 * last arg.
7227 */
7228 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7229 line++;
7230 *line = '\0';
7231
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007232 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007233 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007234 err_code |= ERR_ALERT | ERR_FATAL;
7235 args[arg] = line;
7236 }
7237
Willy Tarreau540abe42007-05-02 20:50:16 +02007238 /* zero out remaining args and ensure that at least one entry
7239 * is zeroed out.
7240 */
7241 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007242 args[arg] = line;
7243 }
7244
Willy Tarreau3842f002009-06-14 11:39:52 +02007245 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007246 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007247 char *tmp;
7248
Willy Tarreau3842f002009-06-14 11:39:52 +02007249 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007250 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007251 for (arg=0; *args[arg+1]; arg++)
7252 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007253 *tmp = '\0'; // fix the next arg to \0
7254 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007255 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007256 else if (!strcmp(args[0], "default")) {
7257 kwm = KWM_DEF;
7258 for (arg=0; *args[arg+1]; arg++)
7259 args[arg] = args[arg+1]; // shift args after inversion
7260 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007261
William Lallemand0f99e342011-10-12 17:50:54 +02007262 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7263 strcmp(args[0], "log") != 0) {
7264 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007265 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007266 }
7267
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007268 /* detect section start */
7269 list_for_each_entry(ics, &sections, list) {
7270 if (strcmp(args[0], ics->section_name) == 0) {
7271 cursection = ics->section_name;
7272 cs = ics;
7273 break;
7274 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007275 }
7276
Willy Tarreaubaaee002006-06-26 02:48:02 +02007277 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007278 if (cs)
7279 err_code |= cs->section_parser(file, linenum, args, kwm);
7280 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007281 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007282 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007283 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007284
7285 if (err_code & ERR_ABORT)
7286 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007287 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007288 free(cfg_scope);
7289 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007290 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007291 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007292 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007293 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007294}
7295
Willy Tarreau64ab6072014-09-16 12:17:36 +02007296/* This function propagates processes from frontend <from> to backend <to> so
7297 * that it is always guaranteed that a backend pointed to by a frontend is
7298 * bound to all of its processes. After that, if the target is a "listen"
7299 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007300 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007301 * checked first to ensure that <to> is already bound to all processes of
7302 * <from>, there is no risk of looping and we ensure to follow the shortest
7303 * path to the destination.
7304 *
7305 * It is possible to set <to> to NULL for the first call so that the function
7306 * takes care of visiting the initial frontend in <from>.
7307 *
7308 * It is important to note that the function relies on the fact that all names
7309 * have already been resolved.
7310 */
7311void propagate_processes(struct proxy *from, struct proxy *to)
7312{
7313 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007314
7315 if (to) {
7316 /* check whether we need to go down */
7317 if (from->bind_proc &&
7318 (from->bind_proc & to->bind_proc) == from->bind_proc)
7319 return;
7320
7321 if (!from->bind_proc && !to->bind_proc)
7322 return;
7323
7324 to->bind_proc = from->bind_proc ?
7325 (to->bind_proc | from->bind_proc) : 0;
7326
7327 /* now propagate down */
7328 from = to;
7329 }
7330
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007331 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007332 return;
7333
Willy Tarreauf6b70012014-12-18 14:00:43 +01007334 if (from->state == PR_STSTOPPED)
7335 return;
7336
Willy Tarreau64ab6072014-09-16 12:17:36 +02007337 /* default_backend */
7338 if (from->defbe.be)
7339 propagate_processes(from, from->defbe.be);
7340
7341 /* use_backend */
7342 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007343 if (rule->dynamic)
7344 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007345 to = rule->be.backend;
7346 propagate_processes(from, to);
7347 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007348}
7349
Willy Tarreaubb925012009-07-23 13:36:36 +02007350/*
7351 * Returns the error code, 0 if OK, or any combination of :
7352 * - ERR_ABORT: must abort ASAP
7353 * - ERR_FATAL: we can continue parsing but not start the service
7354 * - ERR_WARN: a warning has been emitted
7355 * - ERR_ALERT: an alert has been emitted
7356 * Only the two first ones can stop processing, the two others are just
7357 * indicators.
7358 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007359int check_config_validity()
7360{
7361 int cfgerr = 0;
7362 struct proxy *curproxy = NULL;
7363 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007364 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007365 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007366 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007367 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007368
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007369 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007370 /*
7371 * Now, check for the integrity of all that we have collected.
7372 */
7373
7374 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007375 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007376
Willy Tarreau193b8c62012-11-22 00:17:38 +01007377 if (!global.tune.max_http_hdr)
7378 global.tune.max_http_hdr = MAX_HTTP_HDR;
7379
7380 if (!global.tune.cookie_len)
7381 global.tune.cookie_len = CAPTURE_LEN;
7382
Stéphane Cottin23e9e932017-05-18 08:58:41 +02007383 if (!global.tune.requri_len)
7384 global.tune.requri_len = REQURI_LEN;
7385
Willy Tarreau193b8c62012-11-22 00:17:38 +01007386 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7387
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007388 /* Post initialisation of the users and groups lists. */
7389 err_code = userlist_postinit();
7390 if (err_code != ERR_NONE)
7391 goto out;
7392
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007393 /* first, we will invert the proxy list order */
7394 curproxy = NULL;
7395 while (proxy) {
7396 struct proxy *next;
7397
7398 next = proxy->next;
7399 proxy->next = curproxy;
7400 curproxy = proxy;
7401 if (!next)
7402 break;
7403 proxy = next;
7404 }
7405
Willy Tarreau419ead82014-09-16 13:41:21 +02007406 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007407 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007408 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007409 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007410 struct act_rule *trule;
7411 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007412 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007413 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007414 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007415
Willy Tarreau050536d2012-10-04 08:47:34 +02007416 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007417 /* proxy ID not set, use automatic numbering with first
7418 * spare entry starting with next_pxid.
7419 */
7420 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7421 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7422 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007423 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007424 next_pxid++;
7425
Willy Tarreau55ea7572007-06-17 19:56:27 +02007426
Willy Tarreaubaaee002006-06-26 02:48:02 +02007427 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007428 /* ensure we don't keep listeners uselessly bound */
7429 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007430 free((void *)curproxy->table.peers.name);
7431 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007432 continue;
7433 }
7434
Willy Tarreau102df612014-05-07 23:56:38 +02007435 /* Check multi-process mode compatibility for the current proxy */
7436
7437 if (curproxy->bind_proc) {
7438 /* an explicit bind-process was specified, let's check how many
7439 * processes remain.
7440 */
David Carliere6c39412015-07-02 07:00:17 +00007441 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007442
7443 curproxy->bind_proc &= nbits(global.nbproc);
7444 if (!curproxy->bind_proc && nbproc == 1) {
7445 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);
7446 curproxy->bind_proc = 1;
7447 }
7448 else if (!curproxy->bind_proc && nbproc > 1) {
7449 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);
7450 curproxy->bind_proc = 0;
7451 }
7452 }
7453
Willy Tarreau3d209582014-05-09 17:06:11 +02007454 /* check and reduce the bind-proc of each listener */
7455 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7456 unsigned long mask;
7457
7458 if (!bind_conf->bind_proc)
7459 continue;
7460
7461 mask = nbits(global.nbproc);
7462 if (curproxy->bind_proc)
7463 mask &= curproxy->bind_proc;
7464 /* mask cannot be null here thanks to the previous checks */
7465
David Carliere6c39412015-07-02 07:00:17 +00007466 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007467 bind_conf->bind_proc &= mask;
7468
7469 if (!bind_conf->bind_proc && nbproc == 1) {
7470 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",
7471 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7472 bind_conf->bind_proc = mask & ~(mask - 1);
7473 }
7474 else if (!bind_conf->bind_proc && nbproc > 1) {
7475 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",
7476 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7477 bind_conf->bind_proc = 0;
7478 }
7479 }
7480
Willy Tarreauff01a212009-03-15 13:46:16 +01007481 switch (curproxy->mode) {
7482 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007483 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007484 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007485 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7486 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007487 cfgerr++;
7488 }
7489
7490 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007491 Warning("config : servers will be ignored for %s '%s'.\n",
7492 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007493 break;
7494
7495 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007496 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007497 break;
7498
7499 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007500 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007501 break;
7502 }
7503
Willy Tarreauf3934b82015-08-11 11:36:45 +02007504 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7505 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7506 proxy_type_str(curproxy), curproxy->id);
7507 err_code |= ERR_WARN;
7508 }
7509
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007510 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007511 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007512 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007513 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7514 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007515 cfgerr++;
7516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007517#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007518 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007519 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7520 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007521 cfgerr++;
7522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007523#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007524 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007525 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7526 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007527 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007528 }
7529 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007530 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007531 /* If no LB algo is set in a backend, and we're not in
7532 * transparent mode, dispatch mode nor proxy mode, we
7533 * want to use balance roundrobin by default.
7534 */
7535 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7536 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007537 }
7538 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007539
Willy Tarreau1620ec32011-08-06 17:05:02 +02007540 if (curproxy->options & PR_O_DISPATCH)
7541 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7542 else if (curproxy->options & PR_O_HTTP_PROXY)
7543 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7544 else if (curproxy->options & PR_O_TRANSP)
7545 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007546
Willy Tarreau1620ec32011-08-06 17:05:02 +02007547 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7548 if (curproxy->options & PR_O_DISABLE404) {
7549 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7550 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7551 err_code |= ERR_WARN;
7552 curproxy->options &= ~PR_O_DISABLE404;
7553 }
7554 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7555 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7556 "send-state", proxy_type_str(curproxy), curproxy->id);
7557 err_code |= ERR_WARN;
7558 curproxy->options &= ~PR_O2_CHK_SNDST;
7559 }
Willy Tarreauef781042010-01-27 11:53:01 +01007560 }
7561
Simon Horman98637e52014-06-20 12:30:16 +09007562 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7563 if (!global.external_check) {
7564 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7565 curproxy->id, "option external-check");
7566 cfgerr++;
7567 }
7568 if (!curproxy->check_command) {
7569 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7570 curproxy->id, "option external-check");
7571 cfgerr++;
7572 }
7573 }
7574
Simon Horman64e34162015-02-06 11:11:57 +09007575 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007576 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7577 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007578 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7579 "'email-alert myhostname', or 'email-alert to' "
7580 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007581 "to be present).\n",
7582 proxy_type_str(curproxy), curproxy->id);
7583 err_code |= ERR_WARN;
7584 free_email_alert(curproxy);
7585 }
7586 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007587 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007588 }
7589
Simon Horman98637e52014-06-20 12:30:16 +09007590 if (curproxy->check_command) {
7591 int clear = 0;
7592 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7593 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7594 "external-check command", proxy_type_str(curproxy), curproxy->id);
7595 err_code |= ERR_WARN;
7596 clear = 1;
7597 }
7598 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007599 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007600 curproxy->id, "external-check command");
7601 cfgerr++;
7602 }
7603 if (clear) {
7604 free(curproxy->check_command);
7605 curproxy->check_command = NULL;
7606 }
7607 }
7608
7609 if (curproxy->check_path) {
7610 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7611 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7612 "external-check path", proxy_type_str(curproxy), curproxy->id);
7613 err_code |= ERR_WARN;
7614 free(curproxy->check_path);
7615 curproxy->check_path = NULL;
7616 }
7617 }
7618
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007619 /* if a default backend was specified, let's find it */
7620 if (curproxy->defbe.name) {
7621 struct proxy *target;
7622
Willy Tarreauafb39922015-05-26 12:04:09 +02007623 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007624 if (!target) {
7625 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7626 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007627 cfgerr++;
7628 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007629 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7630 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007631 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007632 } else if (target->mode != curproxy->mode &&
7633 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7634
7635 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7636 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7637 curproxy->conf.file, curproxy->conf.line,
7638 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7639 target->conf.file, target->conf.line);
7640 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007641 } else {
7642 free(curproxy->defbe.name);
7643 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007644 /* Update tot_fe_maxconn for a further fullconn's computation */
7645 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007646 /* Emit a warning if this proxy also has some servers */
7647 if (curproxy->srv) {
7648 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7649 curproxy->id);
7650 err_code |= ERR_WARN;
7651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007652 }
7653 }
7654
Emeric Brun3f783572017-01-12 11:21:28 +01007655 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7656 /* Case of listen without default backend
7657 * The curproxy will be its own default backend
7658 * so we update tot_fe_maxconn for a further
7659 * fullconn's computation */
7660 curproxy->tot_fe_maxconn += curproxy->maxconn;
7661 }
7662
Willy Tarreau55ea7572007-06-17 19:56:27 +02007663 /* find the target proxy for 'use_backend' rules */
7664 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007665 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007666 struct logformat_node *node;
7667 char *pxname;
7668
7669 /* Try to parse the string as a log format expression. If the result
7670 * of the parsing is only one entry containing a simple string, then
7671 * it's a standard string corresponding to a static rule, thus the
7672 * parsing is cancelled and be.name is restored to be resolved.
7673 */
7674 pxname = rule->be.name;
7675 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007676 curproxy->conf.args.ctx = ARGC_UBK;
7677 curproxy->conf.args.file = rule->file;
7678 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007679 err = NULL;
7680 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7681 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7682 rule->file, rule->line, pxname, err);
7683 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007684 cfgerr++;
7685 continue;
7686 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007687 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7688
7689 if (!LIST_ISEMPTY(&rule->be.expr)) {
7690 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7691 rule->dynamic = 1;
7692 free(pxname);
7693 continue;
7694 }
7695 /* simple string: free the expression and fall back to static rule */
7696 free(node->arg);
7697 free(node);
7698 }
7699
7700 rule->dynamic = 0;
7701 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007702
Willy Tarreauafb39922015-05-26 12:04:09 +02007703 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007704 if (!target) {
7705 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7706 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007707 cfgerr++;
7708 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007709 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7710 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007711 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007712 } else if (target->mode != curproxy->mode &&
7713 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7714
7715 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7716 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7717 curproxy->conf.file, curproxy->conf.line,
7718 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7719 target->conf.file, target->conf.line);
7720 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007721 } else {
7722 free((void *)rule->be.name);
7723 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007724 /* For each target of switching rules, we update
7725 * their tot_fe_maxconn, except if a previous rule point
7726 * on the same backend or on the default backend */
7727 if (rule->be.backend != curproxy->defbe.be) {
7728 struct switching_rule *swrule;
7729
7730 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7731 if (rule == swrule) {
7732 target->tot_fe_maxconn += curproxy->maxconn;
7733 break;
7734 }
7735 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7736 /* there is multiple ref of this backend */
7737 break;
7738 }
7739 }
7740 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007741 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007742 }
7743
Willy Tarreau64ab6072014-09-16 12:17:36 +02007744 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007745 list_for_each_entry(srule, &curproxy->server_rules, list) {
7746 struct server *target = findserver(curproxy, srule->srv.name);
7747
7748 if (!target) {
7749 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7750 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7751 cfgerr++;
7752 continue;
7753 }
7754 free((void *)srule->srv.name);
7755 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007756 }
7757
Emeric Brunb982a3d2010-01-04 15:45:53 +01007758 /* find the target table for 'stick' rules */
7759 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7760 struct proxy *target;
7761
Emeric Brun1d33b292010-01-04 15:47:17 +01007762 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7763 if (mrule->flags & STK_IS_STORE)
7764 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7765
Emeric Brunb982a3d2010-01-04 15:45:53 +01007766 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007767 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007768 else
7769 target = curproxy;
7770
7771 if (!target) {
7772 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7773 curproxy->id, mrule->table.name);
7774 cfgerr++;
7775 }
7776 else if (target->table.size == 0) {
7777 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7778 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7779 cfgerr++;
7780 }
Willy Tarreau12785782012-04-27 21:37:17 +02007781 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7782 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007783 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7784 cfgerr++;
7785 }
7786 else {
7787 free((void *)mrule->table.name);
7788 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007789 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007790 }
7791 }
7792
7793 /* find the target table for 'store response' rules */
7794 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7795 struct proxy *target;
7796
Emeric Brun1d33b292010-01-04 15:47:17 +01007797 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7798
Emeric Brunb982a3d2010-01-04 15:45:53 +01007799 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007800 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007801 else
7802 target = curproxy;
7803
7804 if (!target) {
7805 Alert("Proxy '%s': unable to find store table '%s'.\n",
7806 curproxy->id, mrule->table.name);
7807 cfgerr++;
7808 }
7809 else if (target->table.size == 0) {
7810 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7811 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7812 cfgerr++;
7813 }
Willy Tarreau12785782012-04-27 21:37:17 +02007814 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7815 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007816 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7817 cfgerr++;
7818 }
7819 else {
7820 free((void *)mrule->table.name);
7821 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007822 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007823 }
7824 }
7825
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007826 /* find the target table for 'tcp-request' layer 4 rules */
7827 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7828 struct proxy *target;
7829
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007830 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007831 continue;
7832
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007833 if (trule->arg.trk_ctr.table.n)
7834 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007835 else
7836 target = curproxy;
7837
7838 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007839 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007840 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007841 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007842 cfgerr++;
7843 }
7844 else if (target->table.size == 0) {
7845 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007846 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007847 cfgerr++;
7848 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007849 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007850 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007851 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007852 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007853 cfgerr++;
7854 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007855 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007856 free(trule->arg.trk_ctr.table.n);
7857 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007858 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007859 * to pass a list of counters to track and allocate them right here using
7860 * stktable_alloc_data_type().
7861 */
7862 }
7863 }
7864
Willy Tarreau620408f2016-10-21 16:37:51 +02007865 /* find the target table for 'tcp-request' layer 5 rules */
7866 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7867 struct proxy *target;
7868
7869 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7870 continue;
7871
7872 if (trule->arg.trk_ctr.table.n)
7873 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7874 else
7875 target = curproxy;
7876
7877 if (!target) {
7878 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7879 curproxy->id, trule->arg.trk_ctr.table.n,
7880 tcp_trk_idx(trule->action));
7881 cfgerr++;
7882 }
7883 else if (target->table.size == 0) {
7884 Alert("Proxy '%s': table '%s' used but not configured.\n",
7885 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7886 cfgerr++;
7887 }
7888 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7889 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7890 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7891 tcp_trk_idx(trule->action));
7892 cfgerr++;
7893 }
7894 else {
7895 free(trule->arg.trk_ctr.table.n);
7896 trule->arg.trk_ctr.table.t = &target->table;
7897 /* Note: if we decide to enhance the track-sc syntax, we may be able
7898 * to pass a list of counters to track and allocate them right here using
7899 * stktable_alloc_data_type().
7900 */
7901 }
7902 }
7903
Willy Tarreaud1f96522010-08-03 19:34:32 +02007904 /* find the target table for 'tcp-request' layer 6 rules */
7905 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7906 struct proxy *target;
7907
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007908 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007909 continue;
7910
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007911 if (trule->arg.trk_ctr.table.n)
7912 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007913 else
7914 target = curproxy;
7915
7916 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007917 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007918 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007919 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007920 cfgerr++;
7921 }
7922 else if (target->table.size == 0) {
7923 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007924 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007925 cfgerr++;
7926 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007927 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007928 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007929 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007930 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007931 cfgerr++;
7932 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007933 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007934 free(trule->arg.trk_ctr.table.n);
7935 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007936 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007937 * to pass a list of counters to track and allocate them right here using
7938 * stktable_alloc_data_type().
7939 */
7940 }
7941 }
7942
Baptiste Assmanne9544932015-11-03 23:31:35 +01007943 /* parse http-request capture rules to ensure id really exists */
7944 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7945 if (hrqrule->action != ACT_CUSTOM ||
7946 hrqrule->action_ptr != http_action_req_capture_by_id)
7947 continue;
7948
7949 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7950 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7951 curproxy->id, hrqrule->arg.capid.idx);
7952 cfgerr++;
7953 }
7954 }
7955
7956 /* parse http-response capture rules to ensure id really exists */
7957 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7958 if (hrqrule->action != ACT_CUSTOM ||
7959 hrqrule->action_ptr != http_action_res_capture_by_id)
7960 continue;
7961
7962 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7963 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7964 curproxy->id, hrqrule->arg.capid.idx);
7965 cfgerr++;
7966 }
7967 }
7968
Willy Tarreau09448f72014-06-25 18:12:15 +02007969 /* find the target table for 'http-request' layer 7 rules */
7970 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7971 struct proxy *target;
7972
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007973 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007974 continue;
7975
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007976 if (hrqrule->arg.trk_ctr.table.n)
7977 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007978 else
7979 target = curproxy;
7980
7981 if (!target) {
7982 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007983 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007984 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007985 cfgerr++;
7986 }
7987 else if (target->table.size == 0) {
7988 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007989 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007990 cfgerr++;
7991 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007992 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007993 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007994 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007995 http_trk_idx(hrqrule->action));
7996 cfgerr++;
7997 }
7998 else {
7999 free(hrqrule->arg.trk_ctr.table.n);
8000 hrqrule->arg.trk_ctr.table.t = &target->table;
8001 /* Note: if we decide to enhance the track-sc syntax, we may be able
8002 * to pass a list of counters to track and allocate them right here using
8003 * stktable_alloc_data_type().
8004 */
8005 }
8006 }
8007
8008 /* find the target table for 'http-response' layer 7 rules */
8009 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8010 struct proxy *target;
8011
8012 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8013 continue;
8014
8015 if (hrqrule->arg.trk_ctr.table.n)
8016 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8017 else
8018 target = curproxy;
8019
8020 if (!target) {
8021 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8022 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8023 http_trk_idx(hrqrule->action));
8024 cfgerr++;
8025 }
8026 else if (target->table.size == 0) {
8027 Alert("Proxy '%s': table '%s' used but not configured.\n",
8028 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8029 cfgerr++;
8030 }
8031 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8032 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8033 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8034 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008035 cfgerr++;
8036 }
8037 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008038 free(hrqrule->arg.trk_ctr.table.n);
8039 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008040 /* Note: if we decide to enhance the track-sc syntax, we may be able
8041 * to pass a list of counters to track and allocate them right here using
8042 * stktable_alloc_data_type().
8043 */
8044 }
8045 }
8046
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008047 /* move any "block" rules at the beginning of the http-request rules */
8048 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8049 /* insert block_rules into http_req_rules at the beginning */
8050 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8051 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8052 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8053 curproxy->http_req_rules.n = curproxy->block_rules.n;
8054 LIST_INIT(&curproxy->block_rules);
8055 }
8056
Emeric Brun32da3c42010-09-23 18:39:19 +02008057 if (curproxy->table.peers.name) {
8058 struct peers *curpeers = peers;
8059
8060 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8061 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8062 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008063 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008064 break;
8065 }
8066 }
8067
8068 if (!curpeers) {
8069 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8070 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008071 free((void *)curproxy->table.peers.name);
8072 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008073 cfgerr++;
8074 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008075 else if (curpeers->state == PR_STSTOPPED) {
8076 /* silently disable this peers section */
8077 curproxy->table.peers.p = NULL;
8078 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008079 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008080 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8081 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008082 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008083 cfgerr++;
8084 }
8085 }
8086
Simon Horman9dc49962015-01-30 11:22:59 +09008087
8088 if (curproxy->email_alert.mailers.name) {
8089 struct mailers *curmailers = mailers;
8090
8091 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8092 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8093 free(curproxy->email_alert.mailers.name);
8094 curproxy->email_alert.mailers.m = curmailers;
8095 curmailers->users++;
8096 break;
8097 }
8098 }
8099
8100 if (!curmailers) {
8101 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8102 curproxy->id, curproxy->email_alert.mailers.name);
8103 free_email_alert(curproxy);
8104 cfgerr++;
8105 }
8106 }
8107
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008108 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008109 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008110 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8111 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8112 "proxy", curproxy->id);
8113 cfgerr++;
8114 goto out_uri_auth_compat;
8115 }
8116
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008117 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008118 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008119 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008120 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008121
Willy Tarreau95fa4692010-02-01 13:05:50 +01008122 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8123 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008124
8125 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008126 uri_auth_compat_req[i++] = "realm";
8127 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8128 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008129
Willy Tarreau95fa4692010-02-01 13:05:50 +01008130 uri_auth_compat_req[i++] = "unless";
8131 uri_auth_compat_req[i++] = "{";
8132 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8133 uri_auth_compat_req[i++] = "}";
8134 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008135
Willy Tarreauff011f22011-01-06 17:51:27 +01008136 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8137 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008138 cfgerr++;
8139 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008140 }
8141
Willy Tarreauff011f22011-01-06 17:51:27 +01008142 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008143
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008144 if (curproxy->uri_auth->auth_realm) {
8145 free(curproxy->uri_auth->auth_realm);
8146 curproxy->uri_auth->auth_realm = NULL;
8147 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008148
8149 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008150 }
8151out_uri_auth_compat:
8152
Dragan Dosen43885c72015-10-01 13:18:13 +02008153 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008154 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008155 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8156 if (!curproxy->conf.logformat_sd_string) {
8157 /* set the default logformat_sd_string */
8158 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8159 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008160 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008161 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008162 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008163
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008164 /* compile the log format */
8165 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008166 if (curproxy->conf.logformat_string != default_http_log_format &&
8167 curproxy->conf.logformat_string != default_tcp_log_format &&
8168 curproxy->conf.logformat_string != clf_http_log_format)
8169 free(curproxy->conf.logformat_string);
8170 curproxy->conf.logformat_string = NULL;
8171 free(curproxy->conf.lfs_file);
8172 curproxy->conf.lfs_file = NULL;
8173 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008174
8175 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8176 free(curproxy->conf.logformat_sd_string);
8177 curproxy->conf.logformat_sd_string = NULL;
8178 free(curproxy->conf.lfsd_file);
8179 curproxy->conf.lfsd_file = NULL;
8180 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008181 }
8182
Willy Tarreau62a61232013-04-12 18:13:46 +02008183 if (curproxy->conf.logformat_string) {
8184 curproxy->conf.args.ctx = ARGC_LOG;
8185 curproxy->conf.args.file = curproxy->conf.lfs_file;
8186 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008187 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008188 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008189 SMP_VAL_FE_LOG_END, &err)) {
8190 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8191 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8192 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008193 cfgerr++;
8194 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008195 curproxy->conf.args.file = NULL;
8196 curproxy->conf.args.line = 0;
8197 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008198
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008199 if (curproxy->conf.logformat_sd_string) {
8200 curproxy->conf.args.ctx = ARGC_LOGSD;
8201 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8202 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008203 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008204 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 +01008205 SMP_VAL_FE_LOG_END, &err)) {
8206 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8207 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8208 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008209 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008210 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8211 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8212 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8213 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008214 cfgerr++;
8215 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008216 curproxy->conf.args.file = NULL;
8217 curproxy->conf.args.line = 0;
8218 }
8219
Willy Tarreau62a61232013-04-12 18:13:46 +02008220 if (curproxy->conf.uniqueid_format_string) {
8221 curproxy->conf.args.ctx = ARGC_UIF;
8222 curproxy->conf.args.file = curproxy->conf.uif_file;
8223 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008224 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008225 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 +01008226 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8227 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8228 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8229 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008230 cfgerr++;
8231 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008232 curproxy->conf.args.file = NULL;
8233 curproxy->conf.args.line = 0;
8234 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008235
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008236 /* only now we can check if some args remain unresolved.
8237 * This must be done after the users and groups resolution.
8238 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008239 cfgerr += smp_resolve_args(curproxy);
8240 if (!cfgerr)
8241 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008242
Willy Tarreau2738a142006-07-08 17:28:09 +02008243 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008244 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008245 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008246 (!curproxy->timeout.connect ||
8247 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008248 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008249 " | While not properly invalid, you will certainly encounter various problems\n"
8250 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008251 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008252 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008253 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008254 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008255
Willy Tarreau1fa31262007-12-03 00:36:16 +01008256 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8257 * We must still support older configurations, so let's find out whether those
8258 * parameters have been set or must be copied from contimeouts.
8259 */
8260 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008261 if (!curproxy->timeout.tarpit ||
8262 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008263 /* tarpit timeout not set. We search in the following order:
8264 * default.tarpit, curr.connect, default.connect.
8265 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008266 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008267 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008268 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008269 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008270 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008271 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008272 }
8273 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008274 (!curproxy->timeout.queue ||
8275 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008276 /* queue timeout not set. We search in the following order:
8277 * default.queue, curr.connect, default.connect.
8278 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008279 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008280 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008281 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008282 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008283 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008284 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008285 }
8286 }
8287
Willy Tarreau1620ec32011-08-06 17:05:02 +02008288 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008289 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008290 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008291 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008292 }
8293
Willy Tarreau215663d2014-06-13 18:30:23 +02008294 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8295 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8296 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8297 proxy_type_str(curproxy), curproxy->id);
8298 err_code |= ERR_WARN;
8299 }
8300
Willy Tarreau193b8c62012-11-22 00:17:38 +01008301 /* ensure that cookie capture length is not too large */
8302 if (curproxy->capture_len >= global.tune.cookie_len) {
8303 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8304 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8305 err_code |= ERR_WARN;
8306 curproxy->capture_len = global.tune.cookie_len - 1;
8307 }
8308
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008309 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008310 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008311 curproxy->req_cap_pool = create_pool("ptrcap",
8312 curproxy->nb_req_cap * sizeof(char *),
8313 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008314 }
8315
8316 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008317 curproxy->rsp_cap_pool = create_pool("ptrcap",
8318 curproxy->nb_rsp_cap * sizeof(char *),
8319 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008320 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008321
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008322 switch (curproxy->load_server_state_from_file) {
8323 case PR_SRV_STATE_FILE_UNSPEC:
8324 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8325 break;
8326 case PR_SRV_STATE_FILE_GLOBAL:
8327 if (!global.server_state_file) {
8328 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",
8329 curproxy->id);
8330 err_code |= ERR_WARN;
8331 }
8332 break;
8333 }
8334
Willy Tarreaubaaee002006-06-26 02:48:02 +02008335 /* first, we will invert the servers list order */
8336 newsrv = NULL;
8337 while (curproxy->srv) {
8338 struct server *next;
8339
8340 next = curproxy->srv->next;
8341 curproxy->srv->next = newsrv;
8342 newsrv = curproxy->srv;
8343 if (!next)
8344 break;
8345 curproxy->srv = next;
8346 }
8347
Willy Tarreau17edc812014-01-03 12:14:34 +01008348 /* Check that no server name conflicts. This causes trouble in the stats.
8349 * We only emit a warning for the first conflict affecting each server,
8350 * in order to avoid combinatory explosion if all servers have the same
8351 * name. We do that only for servers which do not have an explicit ID,
8352 * because these IDs were made also for distinguishing them and we don't
8353 * want to annoy people who correctly manage them.
8354 */
8355 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8356 struct server *other_srv;
8357
8358 if (newsrv->puid)
8359 continue;
8360
8361 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8362 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8363 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8364 newsrv->conf.file, newsrv->conf.line,
8365 proxy_type_str(curproxy), curproxy->id,
8366 newsrv->id, other_srv->conf.line);
8367 break;
8368 }
8369 }
8370 }
8371
Willy Tarreaudd701652010-05-25 23:03:02 +02008372 /* assign automatic UIDs to servers which don't have one yet */
8373 next_id = 1;
8374 newsrv = curproxy->srv;
8375 while (newsrv != NULL) {
8376 if (!newsrv->puid) {
8377 /* server ID not set, use automatic numbering with first
8378 * spare entry starting with next_svid.
8379 */
8380 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8381 newsrv->conf.id.key = newsrv->puid = next_id;
8382 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8383 }
8384 next_id++;
8385 newsrv = newsrv->next;
8386 }
8387
Willy Tarreau20697042007-11-15 23:26:18 +01008388 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008389 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008390
Willy Tarreau62c3be22012-01-20 13:12:32 +01008391 /*
8392 * If this server supports a maxconn parameter, it needs a dedicated
8393 * tasks to fill the emptied slots when a connection leaves.
8394 * Also, resolve deferred tracking dependency if needed.
8395 */
8396 newsrv = curproxy->srv;
8397 while (newsrv != NULL) {
8398 if (newsrv->minconn > newsrv->maxconn) {
8399 /* Only 'minconn' was specified, or it was higher than or equal
8400 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8401 * this will avoid further useless expensive computations.
8402 */
8403 newsrv->maxconn = newsrv->minconn;
8404 } else if (newsrv->maxconn && !newsrv->minconn) {
8405 /* minconn was not specified, so we set it to maxconn */
8406 newsrv->minconn = newsrv->maxconn;
8407 }
8408
Willy Tarreau17d45382016-12-22 21:16:08 +01008409 /* this will also properly set the transport layer for prod and checks */
8410 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8411 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8412 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8413 }
Emeric Brun94324a42012-10-11 14:00:19 +02008414
Willy Tarreau2f075e92013-12-03 11:11:34 +01008415 /* set the check type on the server */
8416 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8417
Willy Tarreau62c3be22012-01-20 13:12:32 +01008418 if (newsrv->trackit) {
8419 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008420 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008421 char *pname, *sname;
8422
8423 pname = newsrv->trackit;
8424 sname = strrchr(pname, '/');
8425
8426 if (sname)
8427 *sname++ = '\0';
8428 else {
8429 sname = pname;
8430 pname = NULL;
8431 }
8432
8433 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008434 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008435 if (!px) {
8436 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8437 proxy_type_str(curproxy), curproxy->id,
8438 newsrv->id, pname);
8439 cfgerr++;
8440 goto next_srv;
8441 }
8442 } else
8443 px = curproxy;
8444
8445 srv = findserver(px, sname);
8446 if (!srv) {
8447 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8448 proxy_type_str(curproxy), curproxy->id,
8449 newsrv->id, sname);
8450 cfgerr++;
8451 goto next_srv;
8452 }
8453
Willy Tarreau32091232014-05-16 13:52:00 +02008454 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8455 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8456 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008457 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008458 "tracking as it does not have any check nor agent enabled.\n",
8459 proxy_type_str(curproxy), curproxy->id,
8460 newsrv->id, px->id, srv->id);
8461 cfgerr++;
8462 goto next_srv;
8463 }
8464
8465 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8466
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008467 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008468 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8469 "belongs to a tracking chain looping back to %s/%s.\n",
8470 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008471 newsrv->id, px->id, srv->id, px->id,
8472 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008473 cfgerr++;
8474 goto next_srv;
8475 }
8476
8477 if (curproxy != px &&
8478 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8479 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8480 "tracking: disable-on-404 option inconsistency.\n",
8481 proxy_type_str(curproxy), curproxy->id,
8482 newsrv->id, px->id, srv->id);
8483 cfgerr++;
8484 goto next_srv;
8485 }
8486
Willy Tarreau62c3be22012-01-20 13:12:32 +01008487 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008488 newsrv->tracknext = srv->trackers;
8489 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008490
8491 free(newsrv->trackit);
8492 newsrv->trackit = NULL;
8493 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008494
8495 /*
8496 * resolve server's resolvers name and update the resolvers pointer
8497 * accordingly
8498 */
8499 if (newsrv->resolvers_id) {
8500 struct dns_resolvers *curr_resolvers;
8501 int found;
8502
8503 found = 0;
8504 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8505 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8506 found = 1;
8507 break;
8508 }
8509 }
8510
8511 if (!found) {
8512 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8513 proxy_type_str(curproxy), curproxy->id,
8514 newsrv->id, newsrv->resolvers_id);
8515 cfgerr++;
8516 } else {
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008517 if (newsrv->resolution)
8518 newsrv->resolution->resolvers = curr_resolvers;
8519 }
8520 }
8521 else {
8522 /* if no resolvers section associated to this server
8523 * we can clean up the associated resolution structure
8524 */
8525 if (newsrv->resolution) {
8526 free(newsrv->resolution->hostname_dn);
8527 newsrv->resolution->hostname_dn = NULL;
8528 free(newsrv->resolution);
8529 newsrv->resolution = NULL;
8530 }
8531 }
8532
Willy Tarreau62c3be22012-01-20 13:12:32 +01008533 next_srv:
8534 newsrv = newsrv->next;
8535 }
8536
Olivier Houchard4e694042017-03-14 20:01:29 +01008537 /*
8538 * Try to generate dynamic cookies for servers now.
8539 * It couldn't be done earlier, since at the time we parsed
8540 * the server line, we may not have known yet that we
8541 * should use dynamic cookies, or the secret key may not
8542 * have been provided yet.
8543 */
8544 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8545 newsrv = curproxy->srv;
8546 while (newsrv != NULL) {
8547 srv_set_dyncookie(newsrv);
8548 newsrv = newsrv->next;
8549 }
8550
8551 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008552 /* We have to initialize the server lookup mechanism depending
8553 * on what LB algorithm was choosen.
8554 */
8555
8556 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8557 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8558 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008559 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8560 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8561 init_server_map(curproxy);
8562 } else {
8563 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8564 fwrr_init_server_groups(curproxy);
8565 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008566 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008567
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008568 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008569 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8570 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8571 fwlc_init_server_tree(curproxy);
8572 } else {
8573 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8574 fas_init_server_tree(curproxy);
8575 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008576 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008577
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008578 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008579 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8580 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8581 chash_init_server_tree(curproxy);
8582 } else {
8583 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8584 init_server_map(curproxy);
8585 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008586 break;
8587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008588
8589 if (curproxy->options & PR_O_LOGASAP)
8590 curproxy->to_log &= ~LW_BYTES;
8591
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008592 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008593 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8594 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008595 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8596 proxy_type_str(curproxy), curproxy->id);
8597 err_code |= ERR_WARN;
8598 }
8599
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008600 if (curproxy->mode != PR_MODE_HTTP) {
8601 int optnum;
8602
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008603 if (curproxy->uri_auth) {
8604 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8605 proxy_type_str(curproxy), curproxy->id);
8606 err_code |= ERR_WARN;
8607 curproxy->uri_auth = NULL;
8608 }
8609
Willy Tarreaude7dc882017-03-10 11:49:21 +01008610 if (curproxy->capture_name) {
8611 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8612 proxy_type_str(curproxy), curproxy->id);
8613 err_code |= ERR_WARN;
8614 }
8615
8616 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8617 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8618 proxy_type_str(curproxy), curproxy->id);
8619 err_code |= ERR_WARN;
8620 }
8621
8622 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8623 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8624 proxy_type_str(curproxy), curproxy->id);
8625 err_code |= ERR_WARN;
8626 }
8627
8628 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8629 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8630 proxy_type_str(curproxy), curproxy->id);
8631 err_code |= ERR_WARN;
8632 }
8633
8634 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8635 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8636 proxy_type_str(curproxy), curproxy->id);
8637 err_code |= ERR_WARN;
8638 }
8639
Willy Tarreau87cf5142011-08-19 22:57:24 +02008640 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008641 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8642 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8643 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008644 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008645 }
8646
8647 if (curproxy->options & PR_O_ORGTO) {
8648 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8649 "originalto", proxy_type_str(curproxy), curproxy->id);
8650 err_code |= ERR_WARN;
8651 curproxy->options &= ~PR_O_ORGTO;
8652 }
8653
8654 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8655 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8656 (curproxy->cap & cfg_opts[optnum].cap) &&
8657 (curproxy->options & cfg_opts[optnum].val)) {
8658 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8659 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8660 err_code |= ERR_WARN;
8661 curproxy->options &= ~cfg_opts[optnum].val;
8662 }
8663 }
8664
8665 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8666 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8667 (curproxy->cap & cfg_opts2[optnum].cap) &&
8668 (curproxy->options2 & cfg_opts2[optnum].val)) {
8669 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8670 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8671 err_code |= ERR_WARN;
8672 curproxy->options2 &= ~cfg_opts2[optnum].val;
8673 }
8674 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008675
Willy Tarreau29fbe512015-08-20 19:35:14 +02008676#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008677 if (curproxy->conn_src.bind_hdr_occ) {
8678 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008679 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008680 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008681 err_code |= ERR_WARN;
8682 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008683#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008684 }
8685
Willy Tarreaubaaee002006-06-26 02:48:02 +02008686 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008687 * ensure that we're not cross-dressing a TCP server into HTTP.
8688 */
8689 newsrv = curproxy->srv;
8690 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008691 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008692 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8693 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008694 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008695 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008696
Willy Tarreau0cec3312011-10-31 13:49:26 +01008697 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8698 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8699 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8700 err_code |= ERR_WARN;
8701 }
8702
Willy Tarreauc93cd162014-05-13 15:54:22 +02008703 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008704 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8705 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8706 err_code |= ERR_WARN;
8707 }
8708
Willy Tarreau29fbe512015-08-20 19:35:14 +02008709#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008710 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8711 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008712 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 +01008713 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008714 err_code |= ERR_WARN;
8715 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008716#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008717
8718 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8719 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8720 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8721 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8722 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8723 Warning("config : %s '%s' : connections to server '%s' use the client's IP address as the source while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'usesrc' and to use the 'forwardfor' option instead.\n",
8724 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8725 err_code |= ERR_WARN;
8726 }
8727
8728
8729 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8730 Warning("config : %s '%s' : connections to server '%s' will have a PROXY protocol header announcing the first client's IP address while http-reuse is enabled and allows the same connection to be shared between multiple clients. It is strongly advised to disable 'send-proxy' and to use the 'forwardfor' option instead.\n",
8731 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8732 err_code |= ERR_WARN;
8733 }
8734 }
8735
Willy Tarreau21d2af32008-02-14 20:25:24 +01008736 newsrv = newsrv->next;
8737 }
8738
Willy Tarreaue42bd962014-09-16 16:21:19 +02008739 /* check if we have a frontend with "tcp-request content" looking at L7
8740 * with no inspect-delay
8741 */
8742 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8743 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008744 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008745 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008746 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008747 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008748 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008749 break;
8750 }
8751
8752 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8753 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8754 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8755 " This means that these rules will randomly find their contents. This can be fixed by"
8756 " setting the tcp-request inspect-delay.\n",
8757 proxy_type_str(curproxy), curproxy->id);
8758 err_code |= ERR_WARN;
8759 }
8760 }
8761
Christopher Fauletd7c91962015-04-30 11:48:27 +02008762 /* Check filter configuration, if any */
8763 cfgerr += flt_check(curproxy);
8764
Willy Tarreauc1a21672009-08-16 22:37:44 +02008765 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008766 if (!curproxy->accept)
8767 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008768
Willy Tarreauc1a21672009-08-16 22:37:44 +02008769 if (curproxy->tcp_req.inspect_delay ||
8770 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008771 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008772
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008773 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008774 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008775 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008776 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008777
8778 /* both TCP and HTTP must check switching rules */
8779 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008780
8781 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008782 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008783 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8784 curproxy->fe_rsp_ana |= AN_RES_FLT_START_FE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008785 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008786 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8787 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008788 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008789 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008790 }
8791
8792 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008793 if (curproxy->tcp_req.inspect_delay ||
8794 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8795 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8796
Emeric Brun97679e72010-09-23 17:56:44 +02008797 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8798 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8799
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008800 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008801 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008802 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008803 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008804
8805 /* If the backend does requires RDP cookie persistence, we have to
8806 * enable the corresponding analyser.
8807 */
8808 if (curproxy->options2 & PR_O2_RDPC_PRST)
8809 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008810
8811 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008812 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008813 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8814 curproxy->be_rsp_ana |= AN_RES_FLT_START_BE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
Christopher Faulet309c6412015-12-02 09:57:32 +01008815 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008816 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8817 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008818 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008819 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008820 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008821 }
8822
8823 /***********************************************************/
8824 /* At this point, target names have already been resolved. */
8825 /***********************************************************/
8826
8827 /* Check multi-process mode compatibility */
8828
8829 if (global.nbproc > 1 && global.stats_fe) {
8830 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8831 unsigned long mask;
8832
8833 mask = nbits(global.nbproc);
8834 if (global.stats_fe->bind_proc)
8835 mask &= global.stats_fe->bind_proc;
8836
8837 if (bind_conf->bind_proc)
8838 mask &= bind_conf->bind_proc;
8839
8840 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008841 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008842 break;
8843 }
8844 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8845 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");
8846 }
8847 }
8848
8849 /* Make each frontend inherit bind-process from its listeners when not specified. */
8850 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8851 if (curproxy->bind_proc)
8852 continue;
8853
8854 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8855 unsigned long mask;
8856
Willy Tarreaue428b082015-05-04 21:57:58 +02008857 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008858 curproxy->bind_proc |= mask;
8859 }
8860
8861 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008862 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008863 }
8864
8865 if (global.stats_fe) {
8866 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8867 unsigned long mask;
8868
Cyril Bonté06181952016-02-24 00:14:54 +01008869 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008870 global.stats_fe->bind_proc |= mask;
8871 }
8872 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008873 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008874 }
8875
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008876 /* propagate bindings from frontends to backends. Don't do it if there
8877 * are any fatal errors as we must not call it with unresolved proxies.
8878 */
8879 if (!cfgerr) {
8880 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8881 if (curproxy->cap & PR_CAP_FE)
8882 propagate_processes(curproxy, NULL);
8883 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008884 }
8885
8886 /* Bind each unbound backend to all processes when not specified. */
8887 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8888 if (curproxy->bind_proc)
8889 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008890 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008891 }
8892
8893 /*******************************************************/
8894 /* At this step, all proxies have a non-null bind_proc */
8895 /*******************************************************/
8896
8897 /* perform the final checks before creating tasks */
8898
8899 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8900 struct listener *listener;
8901 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008902
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008903 /* Configure SSL for each bind line.
8904 * Note: if configuration fails at some point, the ->ctx member
8905 * remains NULL so that listeners can later detach.
8906 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008907 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008908 if (bind_conf->xprt->prepare_bind_conf &&
8909 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008910 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008911 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008912
Willy Tarreaue6b98942007-10-29 01:09:36 +01008913 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008914 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008915 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008916 int nbproc;
8917
8918 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008919 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008920 nbits(global.nbproc));
8921
8922 if (!nbproc) /* no intersection between listener and frontend */
8923 nbproc = 1;
8924
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008925 if (!listener->luid) {
8926 /* listener ID not set, use automatic numbering with first
8927 * spare entry starting with next_luid.
8928 */
8929 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8930 listener->conf.id.key = listener->luid = next_id;
8931 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008932 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008933 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008934
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008935 /* enable separate counters */
8936 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008937 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008938 if (!listener->name)
8939 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008940 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008941
Willy Tarreaue6b98942007-10-29 01:09:36 +01008942 if (curproxy->options & PR_O_TCP_NOLING)
8943 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008944 if (!listener->maxconn)
8945 listener->maxconn = curproxy->maxconn;
8946 if (!listener->backlog)
8947 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008948 if (!listener->maxaccept)
8949 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8950
8951 /* we want to have an optimal behaviour on single process mode to
8952 * maximize the work at once, but in multi-process we want to keep
8953 * some fairness between processes, so we target half of the max
8954 * number of events to be balanced over all the processes the proxy
8955 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8956 * used to disable the limit.
8957 */
8958 if (listener->maxaccept > 0) {
8959 if (nbproc > 1)
8960 listener->maxaccept = (listener->maxaccept + 1) / 2;
8961 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8962 }
8963
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008964 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008965 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008966 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008967 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008968
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008969 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008970 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008971
Willy Tarreau620408f2016-10-21 16:37:51 +02008972 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8973 listener->options |= LI_O_TCP_L5_RULES;
8974
Willy Tarreaude3041d2010-05-31 10:56:17 +02008975 if (curproxy->mon_mask.s_addr)
8976 listener->options |= LI_O_CHK_MONNET;
8977
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008978 /* smart accept mode is automatic in HTTP mode */
8979 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008980 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008981 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8982 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008983 }
8984
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008985 /* Release unused SSL configs */
8986 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008987 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8988 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008989 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008990
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008991 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008992 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008993 int count, maxproc = 0;
8994
8995 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008996 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008997 if (count > maxproc)
8998 maxproc = count;
8999 }
9000 /* backends have 0, frontends have 1 or more */
9001 if (maxproc != 1)
9002 Warning("Proxy '%s': in multi-process mode, stats will be"
9003 " limited to process assigned to the current request.\n",
9004 curproxy->id);
9005
Willy Tarreau102df612014-05-07 23:56:38 +02009006 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
9007 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
9008 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009009 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009010 }
Willy Tarreau102df612014-05-07 23:56:38 +02009011 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
9012 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
9013 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01009014 }
9015 }
Willy Tarreau918ff602011-07-25 16:33:49 +02009016
9017 /* create the task associated with the proxy */
9018 curproxy->task = task_new();
9019 if (curproxy->task) {
9020 curproxy->task->context = curproxy;
9021 curproxy->task->process = manage_proxy;
9022 /* no need to queue, it will be done automatically if some
9023 * listener gets limited.
9024 */
9025 curproxy->task->expire = TICK_ETERNITY;
9026 } else {
9027 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9028 curproxy->id);
9029 cfgerr++;
9030 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009031 }
9032
Willy Tarreaufbb78422011-06-05 15:38:35 +02009033 /* automatically compute fullconn if not set. We must not do it in the
9034 * loop above because cross-references are not yet fully resolved.
9035 */
9036 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9037 /* If <fullconn> is not set, let's set it to 10% of the sum of
9038 * the possible incoming frontend's maxconns.
9039 */
9040 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009041 /* we have the sum of the maxconns in <total>. We only
9042 * keep 10% of that sum to set the default fullconn, with
9043 * a hard minimum of 1 (to avoid a divide by zero).
9044 */
Emeric Brun3f783572017-01-12 11:21:28 +01009045 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009046 if (!curproxy->fullconn)
9047 curproxy->fullconn = 1;
9048 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009049 }
9050
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009051 /*
9052 * Recount currently required checks.
9053 */
9054
9055 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9056 int optnum;
9057
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009058 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9059 if (curproxy->options & cfg_opts[optnum].val)
9060 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009061
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009062 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9063 if (curproxy->options2 & cfg_opts2[optnum].val)
9064 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009065 }
9066
Willy Tarreau0fca4832015-05-01 19:12:05 +02009067 /* compute the required process bindings for the peers */
9068 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9069 if (curproxy->table.peers.p)
9070 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9071
Willy Tarreau122541c2011-09-07 21:24:49 +02009072 if (peers) {
9073 struct peers *curpeers = peers, **last;
9074 struct peer *p, *pb;
9075
Willy Tarreau1e273012015-05-01 19:15:17 +02009076 /* Remove all peers sections which don't have a valid listener,
9077 * which are not used by any table, or which are bound to more
9078 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009079 */
9080 last = &peers;
9081 while (*last) {
9082 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009083
9084 if (curpeers->state == PR_STSTOPPED) {
9085 /* the "disabled" keyword was present */
9086 if (curpeers->peers_fe)
9087 stop_proxy(curpeers->peers_fe);
9088 curpeers->peers_fe = NULL;
9089 }
9090 else if (!curpeers->peers_fe) {
9091 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9092 curpeers->id, localpeer);
9093 }
David Carliere6c39412015-07-02 07:00:17 +00009094 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009095 /* either it's totally stopped or too much used */
9096 if (curpeers->peers_fe->bind_proc) {
9097 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009098 "running in different processes (%d different ones). "
9099 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009100 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009101 cfgerr++;
9102 }
9103 stop_proxy(curpeers->peers_fe);
9104 curpeers->peers_fe = NULL;
9105 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009106 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009107 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009108 last = &curpeers->next;
9109 continue;
9110 }
9111
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009112 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009113 p = curpeers->remote;
9114 while (p) {
9115 pb = p->next;
9116 free(p->id);
9117 free(p);
9118 p = pb;
9119 }
9120
9121 /* Destroy and unlink this curpeers section.
9122 * Note: curpeers is backed up into *last.
9123 */
9124 free(curpeers->id);
9125 curpeers = curpeers->next;
9126 free(*last);
9127 *last = curpeers;
9128 }
9129 }
9130
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009131 /* initialize stick-tables on backend capable proxies. This must not
9132 * be done earlier because the data size may be discovered while parsing
9133 * other proxies.
9134 */
9135 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9136 if (curproxy->state == PR_STSTOPPED)
9137 continue;
9138
9139 if (!stktable_init(&curproxy->table)) {
9140 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9141 cfgerr++;
9142 }
9143 }
9144
Simon Horman0d16a402015-01-30 11:22:58 +09009145 if (mailers) {
9146 struct mailers *curmailers = mailers, **last;
9147 struct mailer *m, *mb;
9148
9149 /* Remove all mailers sections which don't have a valid listener.
9150 * This can happen when a mailers section is never referenced.
9151 */
9152 last = &mailers;
9153 while (*last) {
9154 curmailers = *last;
9155 if (curmailers->users) {
9156 last = &curmailers->next;
9157 continue;
9158 }
9159
9160 Warning("Removing incomplete section 'mailers %s'.\n",
9161 curmailers->id);
9162
9163 m = curmailers->mailer_list;
9164 while (m) {
9165 mb = m->next;
9166 free(m->id);
9167 free(m);
9168 m = mb;
9169 }
9170
9171 /* Destroy and unlink this curmailers section.
9172 * Note: curmailers is backed up into *last.
9173 */
9174 free(curmailers->id);
9175 curmailers = curmailers->next;
9176 free(*last);
9177 *last = curmailers;
9178 }
9179 }
9180
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009181 /* Update server_state_file_name to backend name if backend is supposed to use
9182 * a server-state file locally defined and none has been provided */
9183 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9184 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9185 curproxy->server_state_file_name == NULL)
9186 curproxy->server_state_file_name = strdup(curproxy->id);
9187 }
9188
Willy Tarreau34eb6712011-10-24 18:15:04 +02009189 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009190 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009191 MEM_F_SHARED);
9192
Willy Tarreaubb925012009-07-23 13:36:36 +02009193 if (cfgerr > 0)
9194 err_code |= ERR_ALERT | ERR_FATAL;
9195 out:
9196 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009197}
9198
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009199/*
9200 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9201 * parsing sessions.
9202 */
9203void cfg_register_keywords(struct cfg_kw_list *kwl)
9204{
9205 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9206}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009207
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009208/*
9209 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9210 */
9211void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9212{
9213 LIST_DEL(&kwl->list);
9214 LIST_INIT(&kwl->list);
9215}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009216
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009217/* this function register new section in the haproxy configuration file.
9218 * <section_name> is the name of this new section and <section_parser>
9219 * is the called parser. If two section declaration have the same name,
9220 * only the first declared is used.
9221 */
9222int cfg_register_section(char *section_name,
9223 int (*section_parser)(const char *, int, char **, int))
9224{
9225 struct cfg_section *cs;
9226
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009227 list_for_each_entry(cs, &sections, list) {
9228 if (strcmp(cs->section_name, section_name) == 0) {
9229 Alert("register section '%s': already registered.\n", section_name);
9230 return 0;
9231 }
9232 }
9233
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009234 cs = calloc(1, sizeof(*cs));
9235 if (!cs) {
9236 Alert("register section '%s': out of memory.\n", section_name);
9237 return 0;
9238 }
9239
9240 cs->section_name = section_name;
9241 cs->section_parser = section_parser;
9242
9243 LIST_ADDQ(&sections, &cs->list);
9244
9245 return 1;
9246}
9247
Willy Tarreaubaaee002006-06-26 02:48:02 +02009248/*
David Carlier845efb52015-09-25 11:49:18 +01009249 * free all config section entries
9250 */
9251void cfg_unregister_sections(void)
9252{
9253 struct cfg_section *cs, *ics;
9254
9255 list_for_each_entry_safe(cs, ics, &sections, list) {
9256 LIST_DEL(&cs->list);
9257 free(cs);
9258 }
9259}
9260
Christopher Faulet7110b402016-10-26 11:09:44 +02009261void cfg_backup_sections(struct list *backup_sections)
9262{
9263 struct cfg_section *cs, *ics;
9264
9265 list_for_each_entry_safe(cs, ics, &sections, list) {
9266 LIST_DEL(&cs->list);
9267 LIST_ADDQ(backup_sections, &cs->list);
9268 }
9269}
9270
9271void cfg_restore_sections(struct list *backup_sections)
9272{
9273 struct cfg_section *cs, *ics;
9274
9275 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9276 LIST_DEL(&cs->list);
9277 LIST_ADDQ(&sections, &cs->list);
9278 }
9279}
9280
Willy Tarreau659fbf02016-05-26 17:55:28 +02009281__attribute__((constructor))
9282static void cfgparse_init(void)
9283{
9284 /* Register internal sections */
9285 cfg_register_section("listen", cfg_parse_listen);
9286 cfg_register_section("frontend", cfg_parse_listen);
9287 cfg_register_section("backend", cfg_parse_listen);
9288 cfg_register_section("defaults", cfg_parse_listen);
9289 cfg_register_section("global", cfg_parse_global);
9290 cfg_register_section("userlist", cfg_parse_users);
9291 cfg_register_section("peers", cfg_parse_peers);
9292 cfg_register_section("mailers", cfg_parse_mailers);
9293 cfg_register_section("namespace_list", cfg_parse_netns);
9294 cfg_register_section("resolvers", cfg_parse_resolvers);
9295}
9296
David Carlier845efb52015-09-25 11:49:18 +01009297/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009298 * Local variables:
9299 * c-indent-level: 8
9300 * c-basic-offset: 8
9301 * End:
9302 */