blob: e1b6b3ebabc32b8e097ad69a249350312a9b9847 [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 }
627 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200628 if (alertif_too_many_args(0, file, linenum, args, &err_code))
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 global.mode |= MODE_DEBUG;
631 }
632 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100635 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200637 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100640 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100647 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100650 global.tune.options &= ~GTUNE_USE_SPLICE;
651 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200652 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200655 global.tune.options &= ~GTUNE_USE_GAI;
656 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000657 else if (!strcmp(args[0], "noreuseport")) {
658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
660 global.tune.options &= ~GTUNE_USE_REUSEPORT;
661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 global.mode |= MODE_QUIET;
666 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200667 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(1, file, linenum, args, &err_code))
669 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 if (global.tune.maxpollevents != 0) {
671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT;
673 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200674 }
675 if (*(args[1]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 global.tune.maxpollevents = atol(args[1]);
681 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100682 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 if (global.tune.maxaccept != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 global.tune.maxaccept = atol(args[1]);
696 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200697 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.chksize = atol(args[1]);
706 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100707 else if (!strcmp(args[0], "tune.recv_enough")) {
708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
709 goto out;
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 global.tune.recv_enough = atol(args[1]);
716 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100717 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
719 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100720 if (*(args[1]) == 0) {
721 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
722 err_code |= ERR_ALERT | ERR_FATAL;
723 goto out;
724 }
725 global.tune.buf_limit = atol(args[1]);
726 if (global.tune.buf_limit) {
727 if (global.tune.buf_limit < 3)
728 global.tune.buf_limit = 3;
729 if (global.tune.buf_limit <= global.tune.reserved_bufs)
730 global.tune.buf_limit = global.tune.reserved_bufs + 1;
731 }
732 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100733 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741 global.tune.reserved_bufs = atol(args[1]);
742 if (global.tune.reserved_bufs < 2)
743 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100744 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100746 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200747 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200750 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.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200756 if (global.tune.bufsize <= 0) {
757 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
760 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100761 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100762 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200763 }
764 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200765 if (alertif_too_many_args(1, file, linenum, args, &err_code))
766 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200773 if (global.tune.maxrewrite < 0) {
774 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100779 else if (!strcmp(args[0], "tune.idletimer")) {
780 unsigned int idle;
781 const char *res;
782
William Lallemand1a748ae2015-05-19 16:37:23 +0200783 if (alertif_too_many_args(1, file, linenum, args, &err_code))
784 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100785 if (*(args[1]) == 0) {
786 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790
791 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
792 if (res) {
793 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
794 file, linenum, *res, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798
799 if (idle > 65535) {
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 global.tune.idle_timer = idle;
805 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100806 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200807 if (alertif_too_many_args(1, file, linenum, args, &err_code))
808 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100809 if (global.tune.client_rcvbuf != 0) {
810 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
811 err_code |= ERR_ALERT;
812 goto out;
813 }
814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.client_rcvbuf = atol(args[1]);
820 }
821 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.server_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.server_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.client_sndbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.client_sndbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.server_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.server_sndbuf = atol(args[1]);
865 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200866 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.tune.pipesize = atol(args[1]);
875 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100876 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200877 if (alertif_too_many_args(1, file, linenum, args, &err_code))
878 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884 global.tune.cookie_len = atol(args[1]) + 1;
885 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200886 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200887 if (alertif_too_many_args(1, file, linenum, args, &err_code))
888 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 global.tune.max_http_hdr = atol(args[1]);
895 }
William Lallemandf3747832012-11-09 12:33:10 +0100896 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
898 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100899 if (*args[1]) {
900 global.tune.comp_maxlevel = atoi(args[1]);
901 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
902 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
903 file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 } else {
908 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
909 file, linenum, args[0]);
910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
913 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200914 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
915 if (*args[1]) {
916 global.tune.pattern_cache = atoi(args[1]);
917 if (global.tune.pattern_cache < 0) {
918 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
919 file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923 } else {
924 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
925 file, linenum, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
928 }
929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200931 if (alertif_too_many_args(1, file, linenum, args, &err_code))
932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200934 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100943 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
944 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]);
945 err_code |= ERR_WARN;
946 goto out;
947 }
948
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200951 if (alertif_too_many_args(1, file, linenum, args, &err_code))
952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200954 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT;
956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100963 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
964 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]);
965 err_code |= ERR_WARN;
966 goto out;
967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
Simon Horman98637e52014-06-20 12:30:16 +0900969 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200970 if (alertif_too_many_args(0, file, linenum, args, &err_code))
971 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900972 global.external_check = 1;
973 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200974 /* user/group name handling */
975 else if (!strcmp(args[0], "user")) {
976 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200977 if (alertif_too_many_args(1, file, linenum, args, &err_code))
978 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200979 if (global.uid != 0) {
980 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT;
982 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200983 }
984 errno = 0;
985 ha_user = getpwnam(args[1]);
986 if (ha_user != NULL) {
987 global.uid = (int)ha_user->pw_uid;
988 }
989 else {
990 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 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200992 }
993 }
994 else if (!strcmp(args[0], "group")) {
995 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +0200996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
997 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200998 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200999 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT;
1001 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001002 }
1003 errno = 0;
1004 ha_group = getgrnam(args[1]);
1005 if (ha_group != NULL) {
1006 global.gid = (int)ha_group->gr_gid;
1007 }
1008 else {
1009 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 +02001010 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001011 }
1012 }
1013 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001015 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 if (*(args[1]) == 0) {
1018 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001023 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1024 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1025 file, linenum, args[0], LONGBITS, global.nbproc);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 }
1030 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001031 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 if (global.maxconn != 0) {
1034 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 global.maxconn = atol(args[1]);
1044#ifdef SYSTEM_MAXCONN
1045 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1046 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);
1047 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
1050#endif /* SYSTEM_MAXCONN */
1051 }
Emeric Brun850efd52014-01-29 12:24:34 +01001052 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001053 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1054 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
1060 if (strcmp(args[1],"none") == 0)
1061 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1062 else if (strcmp(args[1],"required") == 0)
1063 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1064 else {
1065 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001070 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001071 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1072 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001073 if (global.cps_lim != 0) {
1074 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1075 err_code |= ERR_ALERT;
1076 goto out;
1077 }
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
1082 }
1083 global.cps_lim = atol(args[1]);
1084 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001085 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001088 if (global.sps_lim != 0) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1090 err_code |= ERR_ALERT;
1091 goto out;
1092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
1097 }
1098 global.sps_lim = atol(args[1]);
1099 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001100 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001101 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1102 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001103 if (global.ssl_lim != 0) {
1104 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1105 err_code |= ERR_ALERT;
1106 goto out;
1107 }
1108 if (*(args[1]) == 0) {
1109 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113 global.ssl_lim = atol(args[1]);
1114 }
William Lallemandd85f9172012-11-09 17:05:39 +01001115 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001116 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1117 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001118 if (*(args[1]) == 0) {
1119 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 global.comp_rate_lim = atoi(args[1]) * 1024;
1124 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001125 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001126 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1127 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001128 if (global.maxpipes != 0) {
1129 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT;
1131 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001132 }
1133 if (*(args[1]) == 0) {
1134 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001137 }
1138 global.maxpipes = atol(args[1]);
1139 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001140 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001141 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1142 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
William Lallemande3a7d992012-11-20 11:25:20 +01001148 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001149 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001150 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001151 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1152 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001153 if (*(args[1]) == 0) {
1154 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto out;
1157 }
1158 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001159 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001160 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001164 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001165
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001167 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 if (global.rlimit_nofile != 0) {
1170 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 global.rlimit_nofile = atol(args[1]);
1180 }
1181 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 if (global.chroot != NULL) {
1185 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001186 err_code |= ERR_ALERT;
1187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001188 }
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
1194 global.chroot = strdup(args[1]);
1195 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001196 else if (!strcmp(args[0], "description")) {
1197 int i, len=0;
1198 char *d;
1199
1200 if (!*args[1]) {
1201 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1202 file, linenum, args[0]);
1203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
1205 }
1206
Willy Tarreau348acfe2014-04-14 15:00:39 +02001207 for (i = 1; *args[i]; i++)
1208 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001209
1210 if (global.desc)
1211 free(global.desc);
1212
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001213 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001214
Willy Tarreau348acfe2014-04-14 15:00:39 +02001215 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1216 for (i = 2; *args[i]; i++)
1217 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001218 }
1219 else if (!strcmp(args[0], "node")) {
1220 int i;
1221 char c;
1222
William Lallemand1a748ae2015-05-19 16:37:23 +02001223 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1224 goto out;
1225
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001226 for (i=0; args[1][i]; i++) {
1227 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001228 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1229 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001230 break;
1231 }
1232
1233 if (!i || args[1][i]) {
1234 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1235 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1236 file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240
1241 if (global.node)
1242 free(global.node);
1243
1244 global.node = strdup(args[1]);
1245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001247 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 if (global.pidfile != NULL) {
1250 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001251 err_code |= ERR_ALERT;
1252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
1254 if (*(args[1]) == 0) {
1255 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 global.pidfile = strdup(args[1]);
1260 }
Emeric Bruned760922010-10-22 17:59:25 +02001261 else if (!strcmp(args[0], "unix-bind")) {
1262 int cur_arg = 1;
1263 while (*(args[cur_arg])) {
1264 if (!strcmp(args[cur_arg], "prefix")) {
1265 if (global.unix_bind.prefix != NULL) {
1266 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1267 err_code |= ERR_ALERT;
1268 cur_arg += 2;
1269 continue;
1270 }
1271
1272 if (*(args[cur_arg+1]) == 0) {
1273 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1278 cur_arg += 2;
1279 continue;
1280 }
1281
1282 if (!strcmp(args[cur_arg], "mode")) {
1283
1284 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1285 cur_arg += 2;
1286 continue;
1287 }
1288
1289 if (!strcmp(args[cur_arg], "uid")) {
1290
1291 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (!strcmp(args[cur_arg], "gid")) {
1297
1298 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (!strcmp(args[cur_arg], "user")) {
1304 struct passwd *user;
1305
1306 user = getpwnam(args[cur_arg + 1]);
1307 if (!user) {
1308 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1309 file, linenum, args[0], args[cur_arg + 1 ]);
1310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
1312 }
1313
1314 global.unix_bind.ux.uid = user->pw_uid;
1315 cur_arg += 2;
1316 continue;
1317 }
1318
1319 if (!strcmp(args[cur_arg], "group")) {
1320 struct group *group;
1321
1322 group = getgrnam(args[cur_arg + 1]);
1323 if (!group) {
1324 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1325 file, linenum, args[0], args[cur_arg + 1 ]);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329
1330 global.unix_bind.ux.gid = group->gr_gid;
1331 cur_arg += 2;
1332 continue;
1333 }
1334
Willy Tarreaub48f9582011-09-05 01:17:06 +02001335 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001336 file, linenum, args[0]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
1340 }
William Lallemand0f99e342011-10-12 17:50:54 +02001341 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1342 /* delete previous herited or defined syslog servers */
1343 struct logsrv *back;
1344 struct logsrv *tmp;
1345
1346 if (*(args[1]) != 0) {
1347 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto out;
1350 }
1351
1352 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1353 LIST_DEL(&tmp->list);
1354 free(tmp);
1355 }
1356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001358 struct sockaddr_storage *sk;
1359 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001360 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001361 int arg = 0;
1362 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001363
William Lallemand1a748ae2015-05-19 16:37:23 +02001364 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1365 goto out;
1366
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 if (*(args[1]) == 0 || *(args[2]) == 0) {
1368 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001369 err_code |= ERR_ALERT | ERR_FATAL;
1370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371 }
William Lallemand0f99e342011-10-12 17:50:54 +02001372
Vincent Bernat02779b62016-04-03 13:48:43 +02001373 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001374
Willy Tarreau18324f52014-06-27 18:10:07 +02001375 /* just after the address, a length may be specified */
1376 if (strcmp(args[arg+2], "len") == 0) {
1377 len = atoi(args[arg+3]);
1378 if (len < 80 || len > 65535) {
1379 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1380 file, linenum, args[arg+3]);
1381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
1383 }
1384 logsrv->maxlen = len;
1385
1386 /* skip these two args */
1387 arg += 2;
1388 }
1389 else
1390 logsrv->maxlen = MAX_SYSLOG_LEN;
1391
1392 if (logsrv->maxlen > global.max_syslog_len) {
1393 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001394 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1395 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1396 logline = my_realloc2(logline, global.max_syslog_len + 1);
1397 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001398 }
1399
Dragan Dosen1322d092015-09-22 16:05:32 +02001400 /* after the length, a format may be specified */
1401 if (strcmp(args[arg+2], "format") == 0) {
1402 logsrv->format = get_log_format(args[arg+3]);
1403 if (logsrv->format < 0) {
1404 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1405 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001406 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001407 goto out;
1408 }
1409
1410 /* skip these two args */
1411 arg += 2;
1412 }
1413
David Carlier97880bb2016-04-08 10:35:26 +01001414 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1415 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001416 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001417 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001418
Willy Tarreau18324f52014-06-27 18:10:07 +02001419 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001420 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001421 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001422 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001423 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001424 }
1425
William Lallemand0f99e342011-10-12 17:50:54 +02001426 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001427 if (*(args[arg+3])) {
1428 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001429 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001430 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434 }
1435
William Lallemand0f99e342011-10-12 17:50:54 +02001436 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001437 if (*(args[arg+4])) {
1438 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001439 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001440 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001441 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001442 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001443 }
1444 }
1445
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001446 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001447 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001448 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001449 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001450 free(logsrv);
1451 goto out;
1452 }
1453 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001454
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001455 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001456 if (port1 != port2) {
1457 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1458 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001459 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001460 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001461 goto out;
1462 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001463
William Lallemand0f99e342011-10-12 17:50:54 +02001464 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001465 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001466 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468
William Lallemand0f99e342011-10-12 17:50:54 +02001469 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001470 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001471 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1472 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001473
1474 if (global.log_send_hostname != NULL) {
1475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1476 err_code |= ERR_ALERT;
1477 goto out;
1478 }
1479
1480 if (*(args[1]))
1481 name = args[1];
1482 else
1483 name = hostname;
1484
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001485 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001486 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001487 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001488 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1489 if (global.server_state_base != NULL) {
1490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1491 err_code |= ERR_ALERT;
1492 goto out;
1493 }
1494
1495 if (!*(args[1])) {
1496 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1497 err_code |= ERR_FATAL;
1498 goto out;
1499 }
1500
1501 global.server_state_base = strdup(args[1]);
1502 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001503 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1504 if (global.server_state_file != NULL) {
1505 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1506 err_code |= ERR_ALERT;
1507 goto out;
1508 }
1509
1510 if (!*(args[1])) {
1511 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1512 err_code |= ERR_FATAL;
1513 goto out;
1514 }
1515
1516 global.server_state_file = strdup(args[1]);
1517 }
Kevinm48936af2010-12-22 16:08:21 +00001518 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001519 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1520 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001521 if (*(args[1]) == 0) {
1522 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
1525 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001526 chunk_destroy(&global.log_tag);
1527 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001528 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001529 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001530 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1531 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001532 if (global.spread_checks != 0) {
1533 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001534 err_code |= ERR_ALERT;
1535 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001536 }
1537 if (*(args[1]) == 0) {
1538 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001541 }
1542 global.spread_checks = atol(args[1]);
1543 if (global.spread_checks < 0 || global.spread_checks > 50) {
1544 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001548 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1549 const char *err;
1550 unsigned int val;
1551
William Lallemand1a748ae2015-05-19 16:37:23 +02001552 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1553 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001554 if (*(args[1]) == 0) {
1555 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
1558 }
1559
1560 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1561 if (err) {
1562 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1563 err_code |= ERR_ALERT | ERR_FATAL;
1564 }
1565 global.max_spread_checks = val;
1566 if (global.max_spread_checks < 0) {
1567 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1568 err_code |= ERR_ALERT | ERR_FATAL;
1569 }
1570 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001571 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1572#ifdef USE_CPU_AFFINITY
1573 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001574 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001575 unsigned long cpus = 0;
1576
1577 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001578 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001579 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001580 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001581 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001582 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001583 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001584 proc = atol(args[1]);
1585 if (proc >= 1 && proc <= LONGBITS)
1586 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001587 }
1588
1589 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001590 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",
1591 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001592 err_code |= ERR_ALERT | ERR_FATAL;
1593 goto out;
1594 }
1595
1596 cur_arg = 2;
1597 while (*args[cur_arg]) {
1598 unsigned int low, high;
1599
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001600 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001601 char *dash = strchr(args[cur_arg], '-');
1602
1603 low = high = str2uic(args[cur_arg]);
1604 if (dash)
1605 high = str2uic(dash + 1);
1606
1607 if (high < low) {
1608 unsigned int swap = low;
1609 low = high;
1610 high = swap;
1611 }
1612
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001614 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
1618 }
1619
1620 while (low <= high)
1621 cpus |= 1UL << low++;
1622 }
1623 else {
1624 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1625 file, linenum, args[0], args[cur_arg]);
1626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
1629 cur_arg++;
1630 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001631 for (i = 0; i < LONGBITS; i++)
1632 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001633 global.cpu_map[i] = cpus;
1634#else
1635 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
1638#endif
1639 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001640 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1641 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1642 goto out;
1643
1644 if (*(args[2]) == 0) {
1645 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1646 err_code |= ERR_ALERT | ERR_FATAL;
1647 goto out;
1648 }
1649
1650 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1651 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1652 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
1656 }
1657 else if (!strcmp(args[0], "unsetenv")) {
1658 int arg;
1659
1660 if (*(args[1]) == 0) {
1661 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
1664 }
1665
1666 for (arg = 1; *args[arg]; arg++) {
1667 if (unsetenv(args[arg]) != 0) {
1668 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1669 err_code |= ERR_ALERT | ERR_FATAL;
1670 goto out;
1671 }
1672 }
1673 }
1674 else if (!strcmp(args[0], "resetenv")) {
1675 extern char **environ;
1676 char **env = environ;
1677
1678 /* args contain variable names to keep, one per argument */
1679 while (*env) {
1680 int arg;
1681
1682 /* look for current variable in among all those we want to keep */
1683 for (arg = 1; *args[arg]; arg++) {
1684 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1685 (*env)[strlen(args[arg])] == '=')
1686 break;
1687 }
1688
1689 /* delete this variable */
1690 if (!*args[arg]) {
1691 char *delim = strchr(*env, '=');
1692
1693 if (!delim || delim - *env >= trash.size) {
1694 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
1698
1699 memcpy(trash.str, *env, delim - *env);
1700 trash.str[delim - *env] = 0;
1701
1702 if (unsetenv(trash.str) != 0) {
1703 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707 }
1708 else
1709 env++;
1710 }
1711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001713 struct cfg_kw_list *kwl;
1714 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001715 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001716
1717 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1718 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1719 if (kwl->kw[index].section != CFG_GLOBAL)
1720 continue;
1721 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001722 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001723 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001724 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001726 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001727 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001728 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001729 err_code |= ERR_WARN;
1730 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001731 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001732 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001733 }
1734 }
1735 }
1736
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001740
Willy Tarreau058e9072009-07-20 09:30:05 +02001741 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001742 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001743 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744}
1745
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001746void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001748 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749 defproxy.mode = PR_MODE_TCP;
1750 defproxy.state = PR_STNEW;
1751 defproxy.maxconn = cfg_maxpconn;
1752 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001753 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001754 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001755
Simon Horman66183002013-02-23 10:16:43 +09001756 defproxy.defsrv.check.inter = DEF_CHKINTR;
1757 defproxy.defsrv.check.fastinter = 0;
1758 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001759 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1760 defproxy.defsrv.agent.fastinter = 0;
1761 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001762 defproxy.defsrv.check.rise = DEF_RISETIME;
1763 defproxy.defsrv.check.fall = DEF_FALLTIME;
1764 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1765 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001766 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001767 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001768 defproxy.defsrv.maxqueue = 0;
1769 defproxy.defsrv.minconn = 0;
1770 defproxy.defsrv.maxconn = 0;
1771 defproxy.defsrv.slowstart = 0;
1772 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1773 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1774 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001775
1776 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001777 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778}
1779
Willy Tarreauade5ec42010-01-28 19:33:49 +01001780
Willy Tarreau63af98d2014-05-18 08:11:41 +02001781/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1782 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1783 * ERR_FATAL in case of error.
1784 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001785static int create_cond_regex_rule(const char *file, int line,
1786 struct proxy *px, int dir, int action, int flags,
1787 const char *cmd, const char *reg, const char *repl,
1788 const char **cond_start)
1789{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001790 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001791 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001792 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001793 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001794 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001795 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001796 int cs;
1797 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001798
1799 if (px == &defproxy) {
1800 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001801 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001802 goto err;
1803 }
1804
1805 if (*reg == 0) {
1806 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001807 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001808 goto err;
1809 }
1810
Christopher Faulet898566e2016-10-26 11:06:28 +02001811 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001813
Willy Tarreau5321c422010-01-28 20:35:13 +01001814 if (cond_start &&
1815 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001816 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1817 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1818 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001819 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001820 goto err;
1821 }
1822 }
1823 else if (cond_start && **cond_start) {
1824 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1825 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001826 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001827 goto err;
1828 }
1829
Willy Tarreau63af98d2014-05-18 08:11:41 +02001830 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001831 (dir == SMP_OPT_DIR_REQ) ?
1832 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1833 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1834 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001835
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001836 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001837 if (!preg) {
1838 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001839 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001840 goto err;
1841 }
1842
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001843 cs = !(flags & REG_ICASE);
1844 cap = !(flags & REG_NOSUB);
1845 error = NULL;
1846 if (!regex_comp(reg, preg, cs, cap, &error)) {
1847 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1848 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001849 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001850 goto err;
1851 }
1852
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001853 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001854 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001855 if (repl && err) {
1856 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1857 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001858 ret_code |= ERR_ALERT | ERR_FATAL;
1859 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001860 }
1861
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001862 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code |= ERR_WARN;
1864
1865 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001866
Willy Tarreau63af98d2014-05-18 08:11:41 +02001867 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001868 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001869 err:
1870 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001871 free(errmsg);
1872 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001873}
1874
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875/*
William Lallemand51097192015-04-14 16:35:22 +02001876 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001877 * Returns the error code, 0 if OK, or any combination of :
1878 * - ERR_ABORT: must abort ASAP
1879 * - ERR_FATAL: we can continue parsing but not start the service
1880 * - ERR_WARN: a warning has been emitted
1881 * - ERR_ALERT: an alert has been emitted
1882 * Only the two first ones can stop processing, the two others are just
1883 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001885int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1886{
1887 static struct peers *curpeers = NULL;
1888 struct peer *newpeer = NULL;
1889 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001890 struct bind_conf *bind_conf;
1891 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001892 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001893 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001894
1895 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001896 if (!*args[1]) {
1897 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001898 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001899 goto out;
1900 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001901
William Lallemand6e62fb62015-04-28 16:55:23 +02001902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1903 goto out;
1904
Emeric Brun32da3c42010-09-23 18:39:19 +02001905 err = invalid_char(args[1]);
1906 if (err) {
1907 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1908 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001909 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001910 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 }
1912
1913 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1914 /*
1915 * If there are two proxies with the same name only following
1916 * combinations are allowed:
1917 */
1918 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001919 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 +02001920 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 }
1923 }
1924
Vincent Bernat02779b62016-04-03 13:48:43 +02001925 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001926 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1927 err_code |= ERR_ALERT | ERR_ABORT;
1928 goto out;
1929 }
1930
1931 curpeers->next = peers;
1932 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001933 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001934 curpeers->conf.line = linenum;
1935 curpeers->last_change = now.tv_sec;
1936 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001937 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 }
1939 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001940 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001941 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001942 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001943
1944 if (!*args[2]) {
1945 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1946 file, linenum, args[0]);
1947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
1949 }
1950
1951 err = invalid_char(args[1]);
1952 if (err) {
1953 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1954 file, linenum, *err, args[1]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
Vincent Bernat02779b62016-04-03 13:48:43 +02001959 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001960 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1961 err_code |= ERR_ALERT | ERR_ABORT;
1962 goto out;
1963 }
1964
1965 /* the peers are linked backwards first */
1966 curpeers->count++;
1967 newpeer->next = curpeers->remote;
1968 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001969 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001970 newpeer->conf.line = linenum;
1971
1972 newpeer->last_change = now.tv_sec;
1973 newpeer->id = strdup(args[1]);
1974
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001975 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001976 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001977 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001980 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001981
1982 proto = protocol_by_family(sk->ss_family);
1983 if (!proto || !proto->connect) {
1984 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1985 file, linenum, args[0], args[1]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001989
1990 if (port1 != port2) {
1991 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1992 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
1995 }
1996
Willy Tarreau2aa38802013-02-20 19:20:59 +01001997 if (!port1) {
1998 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1999 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
2002 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002003
Emeric Brun32da3c42010-09-23 18:39:19 +02002004 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002005 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002006 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002007 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 if (strcmp(newpeer->id, localpeer) == 0) {
2010 /* Current is local peer, it define a frontend */
2011 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002012 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002013
2014 if (!curpeers->peers_fe) {
2015 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2017 err_code |= ERR_ALERT | ERR_ABORT;
2018 goto out;
2019 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002020
Willy Tarreau237250c2011-07-29 01:49:03 +02002021 init_new_proxy(curpeers->peers_fe);
2022 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002023 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002024 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2025 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002026 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002027
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002028 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002029
Willy Tarreau902636f2013-03-10 19:44:48 +01002030 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2031 if (errmsg && *errmsg) {
2032 indent_msg(&errmsg, 2);
2033 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002034 }
2035 else
2036 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2037 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 err_code |= ERR_FATAL;
2039 goto out;
2040 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002041
2042 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002043 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002044 l->maxconn = curpeers->peers_fe->maxconn;
2045 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002046 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002047 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002048 l->analysers |= curpeers->peers_fe->fe_req_ana;
2049 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002050 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2051 global.maxsock += l->maxconn;
2052 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002053 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002054 else {
2055 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2056 file, linenum, args[0], args[1],
2057 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2058 err_code |= ERR_FATAL;
2059 goto out;
2060 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002061 }
2062 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002063 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2064 curpeers->state = PR_STSTOPPED;
2065 }
2066 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2067 curpeers->state = PR_STNEW;
2068 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 else if (*args[0] != 0) {
2070 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002076 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002077 return err_code;
2078}
2079
Baptiste Assmann325137d2015-04-13 23:40:55 +02002080/*
2081 * Parse a <resolvers> section.
2082 * Returns the error code, 0 if OK, or any combination of :
2083 * - ERR_ABORT: must abort ASAP
2084 * - ERR_FATAL: we can continue parsing but not start the service
2085 * - ERR_WARN: a warning has been emitted
2086 * - ERR_ALERT: an alert has been emitted
2087 * Only the two first ones can stop processing, the two others are just
2088 * indicators.
2089 */
2090int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2091{
2092 static struct dns_resolvers *curr_resolvers = NULL;
2093 struct dns_nameserver *newnameserver = NULL;
2094 const char *err;
2095 int err_code = 0;
2096 char *errmsg = NULL;
2097
2098 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2099 if (!*args[1]) {
2100 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2101 err_code |= ERR_ALERT | ERR_ABORT;
2102 goto out;
2103 }
2104
2105 err = invalid_char(args[1]);
2106 if (err) {
2107 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2108 file, linenum, *err, args[0], args[1]);
2109 err_code |= ERR_ALERT | ERR_ABORT;
2110 goto out;
2111 }
2112
2113 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2114 /* Error if two resolvers owns the same name */
2115 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2116 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2117 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2118 err_code |= ERR_ALERT | ERR_ABORT;
2119 }
2120 }
2121
Vincent Bernat02779b62016-04-03 13:48:43 +02002122 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2124 err_code |= ERR_ALERT | ERR_ABORT;
2125 goto out;
2126 }
2127
2128 /* default values */
2129 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2130 curr_resolvers->conf.file = strdup(file);
2131 curr_resolvers->conf.line = linenum;
2132 curr_resolvers->id = strdup(args[1]);
2133 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002134 /* default hold period for nx, other, refuse and timeout is 30s */
2135 curr_resolvers->hold.nx = 30000;
2136 curr_resolvers->hold.other = 30000;
2137 curr_resolvers->hold.refused = 30000;
2138 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002139 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002140 curr_resolvers->hold.valid = 10000;
2141 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002142 curr_resolvers->resolve_retries = 3;
2143 LIST_INIT(&curr_resolvers->nameserver_list);
2144 LIST_INIT(&curr_resolvers->curr_resolution);
2145 }
2146 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2147 struct sockaddr_storage *sk;
2148 int port1, port2;
2149 struct protocol *proto;
2150
2151 if (!*args[2]) {
2152 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2153 file, linenum, args[0]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
2157
2158 err = invalid_char(args[1]);
2159 if (err) {
2160 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2161 file, linenum, *err, args[1]);
2162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
2164 }
2165
Baptiste Assmanna315c552015-11-02 22:55:49 +01002166 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2167 /* Error if two resolvers owns the same name */
2168 if (strcmp(newnameserver->id, args[1]) == 0) {
2169 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2170 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2171 err_code |= ERR_ALERT | ERR_FATAL;
2172 }
2173 }
2174
Vincent Bernat02779b62016-04-03 13:48:43 +02002175 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2177 err_code |= ERR_ALERT | ERR_ABORT;
2178 goto out;
2179 }
2180
2181 /* the nameservers are linked backward first */
2182 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2183 curr_resolvers->count_nameservers++;
2184 newnameserver->resolvers = curr_resolvers;
2185 newnameserver->conf.file = strdup(file);
2186 newnameserver->conf.line = linenum;
2187 newnameserver->id = strdup(args[1]);
2188
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002189 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002190 if (!sk) {
2191 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
2196 proto = protocol_by_family(sk->ss_family);
2197 if (!proto || !proto->connect) {
2198 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2199 file, linenum, args[0], args[1]);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
2204 if (port1 != port2) {
2205 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2206 file, linenum, args[0], args[1], args[2]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002211 if (!port1 && !port2) {
2212 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2213 file, linenum, args[0], args[1]);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
2216 }
2217
Baptiste Assmann325137d2015-04-13 23:40:55 +02002218 newnameserver->addr = *sk;
2219 }
2220 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2221 const char *res;
2222 unsigned int time;
2223
2224 if (!*args[2]) {
2225 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2226 file, linenum, args[0]);
2227 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2232 if (res) {
2233 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2234 file, linenum, *res, args[0]);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002238 if (strcmp(args[1], "nx") == 0)
2239 curr_resolvers->hold.nx = time;
2240 else if (strcmp(args[1], "other") == 0)
2241 curr_resolvers->hold.other = time;
2242 else if (strcmp(args[1], "refused") == 0)
2243 curr_resolvers->hold.refused = time;
2244 else if (strcmp(args[1], "timeout") == 0)
2245 curr_resolvers->hold.timeout = time;
2246 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002247 curr_resolvers->hold.valid = time;
2248 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002249 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2250 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254
2255 }
2256 else if (strcmp(args[0], "resolve_retries") == 0) {
2257 if (!*args[1]) {
2258 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2259 file, linenum, args[0]);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263 curr_resolvers->resolve_retries = atoi(args[1]);
2264 }
2265 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002266 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002267 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2268 file, linenum, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002272 else if (strcmp(args[1], "retry") == 0) {
2273 const char *res;
2274 unsigned int timeout_retry;
2275
2276 if (!*args[2]) {
2277 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2278 file, linenum, args[0], args[1]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2283 if (res) {
2284 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2285 file, linenum, *res, args[0], args[1]);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289 curr_resolvers->timeout.retry = timeout_retry;
2290 }
2291 else {
2292 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2293 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002297 } /* neither "nameserver" nor "resolvers" */
2298 else if (*args[0] != 0) {
2299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
2303
2304 out:
2305 free(errmsg);
2306 return err_code;
2307}
Simon Horman0d16a402015-01-30 11:22:58 +09002308
2309/*
William Lallemand51097192015-04-14 16:35:22 +02002310 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002311 * Returns the error code, 0 if OK, or any combination of :
2312 * - ERR_ABORT: must abort ASAP
2313 * - ERR_FATAL: we can continue parsing but not start the service
2314 * - ERR_WARN: a warning has been emitted
2315 * - ERR_ALERT: an alert has been emitted
2316 * Only the two first ones can stop processing, the two others are just
2317 * indicators.
2318 */
2319int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2320{
2321 static struct mailers *curmailers = NULL;
2322 struct mailer *newmailer = NULL;
2323 const char *err;
2324 int err_code = 0;
2325 char *errmsg = NULL;
2326
2327 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2328 if (!*args[1]) {
2329 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2330 err_code |= ERR_ALERT | ERR_ABORT;
2331 goto out;
2332 }
2333
2334 err = invalid_char(args[1]);
2335 if (err) {
2336 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2337 file, linenum, *err, args[0], args[1]);
2338 err_code |= ERR_ALERT | ERR_ABORT;
2339 goto out;
2340 }
2341
2342 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2343 /*
2344 * If there are two proxies with the same name only following
2345 * combinations are allowed:
2346 */
2347 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002348 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 +09002349 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002351 }
2352 }
2353
Vincent Bernat02779b62016-04-03 13:48:43 +02002354 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2356 err_code |= ERR_ALERT | ERR_ABORT;
2357 goto out;
2358 }
2359
2360 curmailers->next = mailers;
2361 mailers = curmailers;
2362 curmailers->conf.file = strdup(file);
2363 curmailers->conf.line = linenum;
2364 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002365 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2366 * But need enough time so that timeouts don't occur
2367 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002368 }
2369 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2370 struct sockaddr_storage *sk;
2371 int port1, port2;
2372 struct protocol *proto;
2373
2374 if (!*args[2]) {
2375 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2376 file, linenum, args[0]);
2377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
2379 }
2380
2381 err = invalid_char(args[1]);
2382 if (err) {
2383 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2384 file, linenum, *err, args[1]);
2385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
2387 }
2388
Vincent Bernat02779b62016-04-03 13:48:43 +02002389 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
2393 }
2394
2395 /* the mailers are linked backwards first */
2396 curmailers->count++;
2397 newmailer->next = curmailers->mailer_list;
2398 curmailers->mailer_list = newmailer;
2399 newmailer->mailers = curmailers;
2400 newmailer->conf.file = strdup(file);
2401 newmailer->conf.line = linenum;
2402
2403 newmailer->id = strdup(args[1]);
2404
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002405 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002406 if (!sk) {
2407 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
2412 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002413 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2414 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002415 file, linenum, args[0], args[1]);
2416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
2418 }
2419
2420 if (port1 != port2) {
2421 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2422 file, linenum, args[0], args[1], args[2]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 if (!port1) {
2428 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2429 file, linenum, args[0], args[1], args[2]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433
2434 newmailer->addr = *sk;
2435 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002436 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002437 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002438 }
2439 else if (strcmp(args[0], "timeout") == 0) {
2440 if (!*args[1]) {
2441 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2442 file, linenum, args[0]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446 else if (strcmp(args[1], "mail") == 0) {
2447 const char *res;
2448 unsigned int timeout_mail;
2449 if (!*args[2]) {
2450 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2451 file, linenum, args[0], args[1]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2456 if (res) {
2457 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2458 file, linenum, *res, args[0]);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462 if (timeout_mail <= 0) {
2463 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467 curmailers->timeout.mail = timeout_mail;
2468 } else {
2469 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2470 file, linenum, args[0], args[1]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
2474 }
Simon Horman0d16a402015-01-30 11:22:58 +09002475 else if (*args[0] != 0) {
2476 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481out:
2482 free(errmsg);
2483 return err_code;
2484}
2485
Simon Horman9dc49962015-01-30 11:22:59 +09002486static void free_email_alert(struct proxy *p)
2487{
2488 free(p->email_alert.mailers.name);
2489 p->email_alert.mailers.name = NULL;
2490 free(p->email_alert.from);
2491 p->email_alert.from = NULL;
2492 free(p->email_alert.to);
2493 p->email_alert.to = NULL;
2494 free(p->email_alert.myhostname);
2495 p->email_alert.myhostname = NULL;
2496}
2497
Willy Tarreau3842f002009-06-14 11:39:52 +02002498int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499{
2500 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002501 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002502 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002503 int rc;
2504 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002505 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002506 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002507 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002508 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002509 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510
Willy Tarreau977b8e42006-12-29 14:19:17 +01002511 if (!strcmp(args[0], "listen"))
2512 rc = PR_CAP_LISTEN;
2513 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002514 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002515 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002516 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002517 else
2518 rc = PR_CAP_NONE;
2519
2520 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 if (!*args[1]) {
2522 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002523 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_ABORT;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002528
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002529 err = invalid_char(args[1]);
2530 if (err) {
2531 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2532 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002534 }
2535
Willy Tarreau8f50b682015-05-26 11:45:02 +02002536 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2537 if (curproxy) {
2538 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2539 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2540 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002542 }
2543
Vincent Bernat02779b62016-04-03 13:48:43 +02002544 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_ABORT;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002549
Willy Tarreau97cb7802010-01-03 20:23:58 +01002550 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 curproxy->next = proxy;
2552 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002553 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2554 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002555 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002558 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559
William Lallemand6e62fb62015-04-28 16:55:23 +02002560 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2561 if (curproxy->cap & PR_CAP_FE)
2562 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565
2566 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002567 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002568 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002572 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002573 curproxy->no_options = defproxy.no_options;
2574 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002575 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002576 curproxy->except_net = defproxy.except_net;
2577 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002578 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002579 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002581 if (defproxy.fwdfor_hdr_len) {
2582 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2583 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2584 }
2585
Willy Tarreaub86db342009-11-30 11:50:16 +01002586 if (defproxy.orgto_hdr_len) {
2587 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2588 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2589 }
2590
Mark Lamourinec2247f02012-01-04 13:02:01 -05002591 if (defproxy.server_id_hdr_len) {
2592 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2593 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2594 }
2595
Willy Tarreau977b8e42006-12-29 14:19:17 +01002596 if (curproxy->cap & PR_CAP_FE) {
2597 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002598 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002599 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600
2601 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002602 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2603 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604
2605 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002609 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002610 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611 curproxy->fullconn = defproxy.fullconn;
2612 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002613 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002614 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002616 if (defproxy.check_req) {
2617 curproxy->check_req = calloc(1, defproxy.check_len);
2618 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2619 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002622 if (defproxy.expect_str) {
2623 curproxy->expect_str = strdup(defproxy.expect_str);
2624 if (defproxy.expect_regex) {
2625 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002626 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2627 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002628 }
2629 }
2630
Willy Tarreau67402132012-05-31 20:40:20 +02002631 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002632 if (defproxy.cookie_name)
2633 curproxy->cookie_name = strdup(defproxy.cookie_name);
2634 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002635
2636 if (defproxy.dyncookie_key)
2637 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002638 if (defproxy.cookie_domain)
2639 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002640
Willy Tarreau31936852010-10-06 16:59:56 +02002641 if (defproxy.cookie_maxidle)
2642 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2643
2644 if (defproxy.cookie_maxlife)
2645 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2646
Emeric Brun647caf12009-06-30 17:57:00 +02002647 if (defproxy.rdp_cookie_name)
2648 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2649 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2650
Willy Tarreau01732802007-11-01 22:48:15 +01002651 if (defproxy.url_param_name)
2652 curproxy->url_param_name = strdup(defproxy.url_param_name);
2653 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002654
Benoitaffb4812009-03-25 13:02:10 +01002655 if (defproxy.hh_name)
2656 curproxy->hh_name = strdup(defproxy.hh_name);
2657 curproxy->hh_len = defproxy.hh_len;
2658 curproxy->hh_match_domain = defproxy.hh_match_domain;
2659
Willy Tarreauef9a3602012-12-08 22:29:20 +01002660 if (defproxy.conn_src.iface_name)
2661 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2662 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002663 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002664#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002665 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002666#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002667 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002670 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671 if (defproxy.capture_name)
2672 curproxy->capture_name = strdup(defproxy.capture_name);
2673 curproxy->capture_namelen = defproxy.capture_namelen;
2674 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676
Willy Tarreau977b8e42006-12-29 14:19:17 +01002677 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002678 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002679 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002680 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002681 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002682 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683 curproxy->mon_net = defproxy.mon_net;
2684 curproxy->mon_mask = defproxy.mon_mask;
2685 if (defproxy.monitor_uri)
2686 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2687 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002688 if (defproxy.defbe.name)
2689 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002690
2691 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002692 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2693 if (curproxy->conf.logformat_string &&
2694 curproxy->conf.logformat_string != default_http_log_format &&
2695 curproxy->conf.logformat_string != default_tcp_log_format &&
2696 curproxy->conf.logformat_string != clf_http_log_format)
2697 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2698
2699 if (defproxy.conf.lfs_file) {
2700 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2701 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2702 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002703
2704 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2705 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2706 if (curproxy->conf.logformat_sd_string &&
2707 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2708 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2709
2710 if (defproxy.conf.lfsd_file) {
2711 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2712 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2713 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 }
2715
2716 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002717 curproxy->timeout.connect = defproxy.timeout.connect;
2718 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002719 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002720 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002721 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002722 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002723 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002724 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002725 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002726 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002727 }
2728
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002730 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002731
2732 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002733 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002734 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002735 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002736 LIST_INIT(&node->list);
2737 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2738 }
2739
Willy Tarreau62a61232013-04-12 18:13:46 +02002740 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2741 if (curproxy->conf.uniqueid_format_string)
2742 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2743
Dragan Dosen43885c72015-10-01 13:18:13 +02002744 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002745
Willy Tarreau62a61232013-04-12 18:13:46 +02002746 if (defproxy.conf.uif_file) {
2747 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2748 curproxy->conf.uif_line = defproxy.conf.uif_line;
2749 }
William Lallemanda73203e2012-03-12 12:48:57 +01002750
2751 /* copy default header unique id */
2752 if (defproxy.header_unique_id)
2753 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2754
William Lallemand82fe75c2012-10-23 10:25:10 +02002755 /* default compression options */
2756 if (defproxy.comp != NULL) {
2757 curproxy->comp = calloc(1, sizeof(struct comp));
2758 curproxy->comp->algos = defproxy.comp->algos;
2759 curproxy->comp->types = defproxy.comp->types;
2760 }
2761
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002763 curproxy->conf.used_listener_id = EB_ROOT;
2764 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002765
Simon Horman98637e52014-06-20 12:30:16 +09002766 if (defproxy.check_path)
2767 curproxy->check_path = strdup(defproxy.check_path);
2768 if (defproxy.check_command)
2769 curproxy->check_command = strdup(defproxy.check_command);
2770
Simon Horman9dc49962015-01-30 11:22:59 +09002771 if (defproxy.email_alert.mailers.name)
2772 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2773 if (defproxy.email_alert.from)
2774 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2775 if (defproxy.email_alert.to)
2776 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2777 if (defproxy.email_alert.myhostname)
2778 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002779 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002780 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002781
Willy Tarreau93893792009-07-23 13:19:11 +02002782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
2784 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2785 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002786 /* FIXME-20070101: we should do this too at the end of the
2787 * config parsing to free all default values.
2788 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002789 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2790 err_code |= ERR_ABORT;
2791 goto out;
2792 }
2793
Willy Tarreaua534fea2008-08-03 12:19:50 +02002794 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002795 free(defproxy.check_command);
2796 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002797 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002798 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002799 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002800 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002801 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002802 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002803 free(defproxy.capture_name);
2804 free(defproxy.monitor_uri);
2805 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002806 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002807 free(defproxy.fwdfor_hdr_name);
2808 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002809 free(defproxy.orgto_hdr_name);
2810 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002811 free(defproxy.server_id_hdr_name);
2812 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002813 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002814 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002815 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002816 free(defproxy.expect_regex);
2817 defproxy.expect_regex = NULL;
2818 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002819
Willy Tarreau62a61232013-04-12 18:13:46 +02002820 if (defproxy.conf.logformat_string != default_http_log_format &&
2821 defproxy.conf.logformat_string != default_tcp_log_format &&
2822 defproxy.conf.logformat_string != clf_http_log_format)
2823 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002824
Willy Tarreau62a61232013-04-12 18:13:46 +02002825 free(defproxy.conf.uniqueid_format_string);
2826 free(defproxy.conf.lfs_file);
2827 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002828 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002829 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002830
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002831 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2832 free(defproxy.conf.logformat_sd_string);
2833 free(defproxy.conf.lfsd_file);
2834
Willy Tarreaua534fea2008-08-03 12:19:50 +02002835 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002836 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002837
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 /* we cannot free uri_auth because it might already be used */
2839 init_default_instance();
2840 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002841 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2842 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002843 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 }
2846 else if (curproxy == NULL) {
2847 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002851
2852 /* update the current file and line being parsed */
2853 curproxy->conf.args.file = curproxy->conf.file;
2854 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002855
2856 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002857 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2858 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2859 if (err_code & ERR_FATAL)
2860 goto out;
2861 }
2862 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002863 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002864 int cur_arg;
2865
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 if (curproxy == &defproxy) {
2867 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002871 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873
Willy Tarreau24709282013-03-10 21:32:12 +01002874 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002875 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002880
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002881 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002882
2883 /* use default settings for unix sockets */
2884 bind_conf->ux.uid = global.unix_bind.ux.uid;
2885 bind_conf->ux.gid = global.unix_bind.ux.gid;
2886 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002887
2888 /* NOTE: the following line might create several listeners if there
2889 * are comma-separated IPs or port ranges. So all further processing
2890 * will have to be applied to all listeners created after last_listen.
2891 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002892 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2893 if (errmsg && *errmsg) {
2894 indent_msg(&errmsg, 2);
2895 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002896 }
2897 else
2898 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2899 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002903
Willy Tarreau4348fad2012-09-20 16:48:07 +02002904 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2905 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002906 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002907 }
2908
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002909 cur_arg = 2;
2910 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002911 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002912 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002913 char *err;
2914
Willy Tarreau26982662012-09-12 23:17:10 +02002915 kw = bind_find_kw(args[cur_arg]);
2916 if (kw) {
2917 char *err = NULL;
2918 int code;
2919
2920 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002921 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2922 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002923 cur_arg += 1 + kw->skip ;
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926 }
2927
Willy Tarreau4348fad2012-09-20 16:48:07 +02002928 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002929 err_code |= code;
2930
2931 if (code) {
2932 if (err && *err) {
2933 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002934 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002935 }
2936 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002937 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2938 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002939 if (code & ERR_FATAL) {
2940 free(err);
2941 cur_arg += 1 + kw->skip;
2942 goto out;
2943 }
2944 }
2945 free(err);
2946 cur_arg += 1 + kw->skip;
2947 continue;
2948 }
2949
Willy Tarreau8638f482012-09-18 18:01:17 +02002950 err = NULL;
2951 if (!bind_dumped) {
2952 bind_dump_kws(&err);
2953 indent_msg(&err, 4);
2954 bind_dumped = 1;
2955 }
2956
2957 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2958 file, linenum, args[0], args[1], args[cur_arg],
2959 err ? " Registered keywords :" : "", err ? err : "");
2960 free(err);
2961
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002964 }
Willy Tarreau93893792009-07-23 13:19:11 +02002965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002968 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2970 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 /* flush useless bits */
2978 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002981 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002982 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002983 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984
William Lallemanddf1425a2015-04-28 20:17:49 +02002985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2986 goto out;
2987
Willy Tarreau1c47f852006-07-09 08:22:27 +02002988 if (!*args[1]) {
2989 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2990 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002993 }
2994
Willy Tarreaua534fea2008-08-03 12:19:50 +02002995 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002996 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002997 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002998 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002999 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3000
Willy Tarreau93893792009-07-23 13:19:11 +02003001 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003004 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3005 goto out;
3006
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3008 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3009 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3010 else {
3011 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
3015 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003016 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003017 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003018
3019 if (curproxy == &defproxy) {
3020 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003024 }
3025
William Lallemanddf1425a2015-04-28 20:17:49 +02003026 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3027 goto out;
3028
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003029 if (!*args[1]) {
3030 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003034 }
3035
3036 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003037 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003038 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003039
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003040 if (curproxy->uuid <= 0) {
3041 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003042 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003045 }
3046
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003047 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3048 if (node) {
3049 struct proxy *target = container_of(node, struct proxy, conf.id);
3050 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3051 file, linenum, proxy_type_str(curproxy), curproxy->id,
3052 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003057 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003058 else if (!strcmp(args[0], "description")) {
3059 int i, len=0;
3060 char *d;
3061
Cyril Bonté99ed3272010-01-24 23:29:44 +01003062 if (curproxy == &defproxy) {
3063 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3064 file, linenum, args[0]);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
3068
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003069 if (!*args[1]) {
3070 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3071 file, linenum, args[0]);
3072 return -1;
3073 }
3074
Willy Tarreau348acfe2014-04-14 15:00:39 +02003075 for (i = 1; *args[i]; i++)
3076 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003077
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003078 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003079 curproxy->desc = d;
3080
Willy Tarreau348acfe2014-04-14 15:00:39 +02003081 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3082 for (i = 2; *args[i]; i++)
3083 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003084
3085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003087 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 curproxy->state = PR_STSTOPPED;
3090 }
3091 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003092 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 curproxy->state = PR_STNEW;
3095 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003096 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3097 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003098 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003099
3100 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003101 unsigned int low, high;
3102
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003103 if (strcmp(args[cur_arg], "all") == 0) {
3104 set = 0;
3105 break;
3106 }
3107 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003108 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003109 }
3110 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003111 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003112 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003113 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003114 char *dash = strchr(args[cur_arg], '-');
3115
3116 low = high = str2uic(args[cur_arg]);
3117 if (dash)
3118 high = str2uic(dash + 1);
3119
3120 if (high < low) {
3121 unsigned int swap = low;
3122 low = high;
3123 high = swap;
3124 }
3125
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003126 if (low < 1 || high > LONGBITS) {
3127 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3128 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003131 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003132 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003133 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003134 }
3135 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003136 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3137 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003140 }
3141 cur_arg++;
3142 }
3143 curproxy->bind_proc = set;
3144 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003145 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003146 if (curproxy == &defproxy) {
3147 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003150 }
3151
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003152 err = invalid_char(args[1]);
3153 if (err) {
3154 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3155 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003157 }
3158
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003159 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003160 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3161 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003164 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003165 }
3166 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3167
3168 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3169 err_code |= ERR_WARN;
3170
3171 if (*(args[1]) == 0) {
3172 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3173 file, linenum, args[0]);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177 free(curproxy->dyncookie_key);
3178 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3181 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182
Willy Tarreau977b8e42006-12-29 14:19:17 +01003183 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003185
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 if (*(args[1]) == 0) {
3187 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3188 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003192
Willy Tarreau67402132012-05-31 20:40:20 +02003193 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003194 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003195 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003196 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 curproxy->cookie_name = strdup(args[1]);
3198 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003199
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 cur_arg = 2;
3201 while (*(args[cur_arg])) {
3202 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003203 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 }
3205 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003206 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003209 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003212 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
3214 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003215 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003217 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003218 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003221 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003223 else if (!strcmp(args[cur_arg], "httponly")) {
3224 curproxy->ck_opts |= PR_CK_HTTPONLY;
3225 }
3226 else if (!strcmp(args[cur_arg], "secure")) {
3227 curproxy->ck_opts |= PR_CK_SECURE;
3228 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003229 else if (!strcmp(args[cur_arg], "domain")) {
3230 if (!*args[cur_arg + 1]) {
3231 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3232 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003235 }
3236
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003237 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003238 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003239 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3240 " dots nor does not start with a dot."
3241 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003242 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003243 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003244 }
3245
3246 err = invalid_domainchar(args[cur_arg + 1]);
3247 if (err) {
3248 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3249 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003252 }
3253
Willy Tarreau68a897b2009-12-03 23:28:34 +01003254 if (!curproxy->cookie_domain) {
3255 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3256 } else {
3257 /* one domain was already specified, add another one by
3258 * building the string which will be returned along with
3259 * the cookie.
3260 */
3261 char *new_ptr;
3262 int new_len = strlen(curproxy->cookie_domain) +
3263 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3264 new_ptr = malloc(new_len);
3265 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3266 free(curproxy->cookie_domain);
3267 curproxy->cookie_domain = new_ptr;
3268 }
Willy Tarreau31936852010-10-06 16:59:56 +02003269 cur_arg++;
3270 }
3271 else if (!strcmp(args[cur_arg], "maxidle")) {
3272 unsigned int maxidle;
3273 const char *res;
3274
3275 if (!*args[cur_arg + 1]) {
3276 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3277 file, linenum, args[cur_arg]);
3278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
3280 }
3281
3282 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3283 if (res) {
3284 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3285 file, linenum, *res, args[cur_arg]);
3286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
3288 }
3289 curproxy->cookie_maxidle = maxidle;
3290 cur_arg++;
3291 }
3292 else if (!strcmp(args[cur_arg], "maxlife")) {
3293 unsigned int maxlife;
3294 const char *res;
3295
3296 if (!*args[cur_arg + 1]) {
3297 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3298 file, linenum, args[cur_arg]);
3299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
3301 }
3302
3303 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3304 if (res) {
3305 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3306 file, linenum, *res, args[cur_arg]);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
3310 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003311 cur_arg++;
3312 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003313 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003314
3315 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3316 err_code |= ERR_WARN;
3317 curproxy->ck_opts |= PR_CK_DYNAMIC;
3318 }
3319
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003321 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 +02003322 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 }
3326 cur_arg++;
3327 }
Willy Tarreau67402132012-05-31 20:40:20 +02003328 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3330 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 }
3333
Willy Tarreau67402132012-05-31 20:40:20 +02003334 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3336 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003339
Willy Tarreau67402132012-05-31 20:40:20 +02003340 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003341 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3342 file, linenum);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003346 else if (!strcmp(args[0], "email-alert")) {
3347 if (*(args[1]) == 0) {
3348 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3349 file, linenum, args[0]);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
3353
3354 if (!strcmp(args[1], "from")) {
3355 if (*(args[1]) == 0) {
3356 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3357 file, linenum, args[1]);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
3361 free(curproxy->email_alert.from);
3362 curproxy->email_alert.from = strdup(args[2]);
3363 }
3364 else if (!strcmp(args[1], "mailers")) {
3365 if (*(args[1]) == 0) {
3366 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3367 file, linenum, args[1]);
3368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
3370 }
3371 free(curproxy->email_alert.mailers.name);
3372 curproxy->email_alert.mailers.name = strdup(args[2]);
3373 }
3374 else if (!strcmp(args[1], "myhostname")) {
3375 if (*(args[1]) == 0) {
3376 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3377 file, linenum, args[1]);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
3381 free(curproxy->email_alert.myhostname);
3382 curproxy->email_alert.myhostname = strdup(args[2]);
3383 }
Simon Horman64e34162015-02-06 11:11:57 +09003384 else if (!strcmp(args[1], "level")) {
3385 curproxy->email_alert.level = get_log_level(args[2]);
3386 if (curproxy->email_alert.level < 0) {
3387 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3388 file, linenum, args[1], args[2]);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
3392 }
Simon Horman9dc49962015-01-30 11:22:59 +09003393 else if (!strcmp(args[1], "to")) {
3394 if (*(args[1]) == 0) {
3395 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3396 file, linenum, args[1]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400 free(curproxy->email_alert.to);
3401 curproxy->email_alert.to = strdup(args[2]);
3402 }
3403 else {
3404 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3405 file, linenum, args[1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
Simon Horman64e34162015-02-06 11:11:57 +09003409 /* Indicate that the email_alert is at least partially configured */
3410 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003411 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003412 else if (!strcmp(args[0], "external-check")) {
3413 if (*(args[1]) == 0) {
3414 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3415 file, linenum, args[0]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
3420 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003421 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003422 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003423 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003424 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3425 file, linenum, args[1]);
3426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
3428 }
3429 free(curproxy->check_command);
3430 curproxy->check_command = strdup(args[2]);
3431 }
3432 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003433 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003434 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003435 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003436 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3437 file, linenum, args[1]);
3438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
3440 }
3441 free(curproxy->check_path);
3442 curproxy->check_path = strdup(args[2]);
3443 }
3444 else {
3445 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3446 file, linenum, args[1]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
3450 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003451 else if (!strcmp(args[0], "persist")) { /* persist */
3452 if (*(args[1]) == 0) {
3453 Alert("parsing [%s:%d] : missing persist method.\n",
3454 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003457 }
3458
3459 if (!strncmp(args[1], "rdp-cookie", 10)) {
3460 curproxy->options2 |= PR_O2_RDPC_PRST;
3461
Emeric Brunb982a3d2010-01-04 15:45:53 +01003462 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003463 const char *beg, *end;
3464
3465 beg = args[1] + 11;
3466 end = strchr(beg, ')');
3467
William Lallemanddf1425a2015-04-28 20:17:49 +02003468 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3469 goto out;
3470
Emeric Brun647caf12009-06-30 17:57:00 +02003471 if (!end || end == beg) {
3472 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3473 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003476 }
3477
3478 free(curproxy->rdp_cookie_name);
3479 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3480 curproxy->rdp_cookie_len = end-beg;
3481 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003482 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003483 free(curproxy->rdp_cookie_name);
3484 curproxy->rdp_cookie_name = strdup("msts");
3485 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3486 }
3487 else { /* syntax */
3488 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3489 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003492 }
3493 }
3494 else {
3495 Alert("parsing [%s:%d] : unknown persist method.\n",
3496 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003499 }
3500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003501 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003502 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003506 else if (!strcmp(args[0], "load-server-state-from-file")) {
3507 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3508 err_code |= ERR_WARN;
3509 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3510 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3511 }
3512 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3513 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3514 }
3515 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3516 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3517 }
3518 else {
3519 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3520 file, linenum, args[0], args[1]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524 }
3525 else if (!strcmp(args[0], "server-state-file-name")) {
3526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3527 err_code |= ERR_WARN;
3528 if (*(args[1]) == 0) {
3529 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3530 file, linenum, args[0]);
3531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
3533 }
3534 else if (!strcmp(args[1], "use-backend-name"))
3535 curproxy->server_state_file_name = strdup(curproxy->id);
3536 else
3537 curproxy->server_state_file_name = strdup(args[1]);
3538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003540 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003542
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003544 if (curproxy == &defproxy) {
3545 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
3548 }
3549
William Lallemand1a748ae2015-05-19 16:37:23 +02003550 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3551 goto out;
3552
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 if (*(args[4]) == 0) {
3554 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003559 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 curproxy->capture_name = strdup(args[2]);
3561 curproxy->capture_namelen = strlen(curproxy->capture_name);
3562 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 curproxy->to_log |= LW_COOKIE;
3564 }
3565 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3566 struct cap_hdr *hdr;
3567
3568 if (curproxy == &defproxy) {
3569 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 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
3573
William Lallemand1a748ae2015-05-19 16:37:23 +02003574 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3575 goto out;
3576
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3578 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3579 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
3583
Vincent Bernat02779b62016-04-03 13:48:43 +02003584 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 hdr->next = curproxy->req_cap;
3586 hdr->name = strdup(args[3]);
3587 hdr->namelen = strlen(args[3]);
3588 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003589 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 hdr->index = curproxy->nb_req_cap++;
3591 curproxy->req_cap = hdr;
3592 curproxy->to_log |= LW_REQHDR;
3593 }
3594 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3595 struct cap_hdr *hdr;
3596
3597 if (curproxy == &defproxy) {
3598 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 +02003599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 }
3602
William Lallemand1a748ae2015-05-19 16:37:23 +02003603 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3604 goto out;
3605
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3607 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3608 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_ALERT | ERR_FATAL;
3610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003612 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 hdr->next = curproxy->rsp_cap;
3614 hdr->name = strdup(args[3]);
3615 hdr->namelen = strlen(args[3]);
3616 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003617 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 hdr->index = curproxy->nb_rsp_cap++;
3619 curproxy->rsp_cap = hdr;
3620 curproxy->to_log |= LW_RSPHDR;
3621 }
3622 else {
3623 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3624 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 }
3628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003630 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003632
William Lallemanddf1425a2015-04-28 20:17:49 +02003633 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3634 goto out;
3635
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 if (*(args[1]) == 0) {
3637 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3638 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 }
3642 curproxy->conn_retries = atol(args[1]);
3643 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003644 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003645 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003646
3647 if (curproxy == &defproxy) {
3648 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
3651 }
3652
Willy Tarreau20b0de52012-12-24 15:45:22 +01003653 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003654 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003655 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3656 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3657 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3658 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003659 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 +01003660 file, linenum, args[0]);
3661 err_code |= ERR_WARN;
3662 }
3663
Willy Tarreauff011f22011-01-06 17:51:27 +01003664 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003665
Willy Tarreauff011f22011-01-06 17:51:27 +01003666 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003667 err_code |= ERR_ALERT | ERR_ABORT;
3668 goto out;
3669 }
3670
Willy Tarreau5002f572014-04-23 01:32:02 +02003671 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003672 err_code |= warnif_cond_conflicts(rule->cond,
3673 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3674 file, linenum);
3675
Willy Tarreauff011f22011-01-06 17:51:27 +01003676 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003677 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003678 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003679 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003680
3681 if (curproxy == &defproxy) {
3682 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
3685 }
3686
3687 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003688 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003689 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3690 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003691 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3692 file, linenum, args[0]);
3693 err_code |= ERR_WARN;
3694 }
3695
3696 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3697
3698 if (!rule) {
3699 err_code |= ERR_ALERT | ERR_ABORT;
3700 goto out;
3701 }
3702
3703 err_code |= warnif_cond_conflicts(rule->cond,
3704 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3705 file, linenum);
3706
3707 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3708 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003709 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3710 /* set the header name and length into the proxy structure */
3711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3712 err_code |= ERR_WARN;
3713
3714 if (!*args[1]) {
3715 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3716 file, linenum, args[0]);
3717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
3719 }
3720
3721 /* set the desired header name */
3722 free(curproxy->server_id_hdr_name);
3723 curproxy->server_id_hdr_name = strdup(args[1]);
3724 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3725 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003726 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003727 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003728
Willy Tarreaub099aca2008-10-12 17:26:37 +02003729 if (curproxy == &defproxy) {
3730 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003733 }
3734
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003735 /* emulate "block" using "http-request block". Since these rules are supposed to
3736 * be processed before all http-request rules, we put them into their own list
3737 * and will insert them at the end.
3738 */
3739 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3740 if (!rule) {
3741 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003742 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003743 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003744 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3745 err_code |= warnif_cond_conflicts(rule->cond,
3746 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3747 file, linenum);
3748 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003749
3750 if (!already_warned(WARN_BLOCK_DEPRECATED))
3751 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]);
3752
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003753 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003754 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003755 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003756
Cyril Bonté99ed3272010-01-24 23:29:44 +01003757 if (curproxy == &defproxy) {
3758 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
3761 }
3762
Willy Tarreaube4653b2015-05-28 15:26:58 +02003763 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003764 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3765 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003768 }
3769
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003770 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003771 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003772 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);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003775 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003776 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003777 struct switching_rule *rule;
3778
Willy Tarreaub099aca2008-10-12 17:26:37 +02003779 if (curproxy == &defproxy) {
3780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003783 }
3784
Willy Tarreau55ea7572007-06-17 19:56:27 +02003785 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003787
3788 if (*(args[1]) == 0) {
3789 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003792 }
3793
Willy Tarreauf51658d2014-04-23 01:21:56 +02003794 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3795 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3796 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3797 file, linenum, errmsg);
3798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
3800 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003801
Willy Tarreauf51658d2014-04-23 01:21:56 +02003802 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003803 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003804 else if (*args[2]) {
3805 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3806 file, linenum, args[2]);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003810
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003811 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003812 if (!rule) {
3813 Alert("Out of memory error.\n");
3814 goto out;
3815 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003816 rule->cond = cond;
3817 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003818 rule->line = linenum;
3819 rule->file = strdup(file);
3820 if (!rule->file) {
3821 Alert("Out of memory error.\n");
3822 goto out;
3823 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003824 LIST_INIT(&rule->list);
3825 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3826 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003827 else if (strcmp(args[0], "use-server") == 0) {
3828 struct server_rule *rule;
3829
3830 if (curproxy == &defproxy) {
3831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835
3836 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3837 err_code |= ERR_WARN;
3838
3839 if (*(args[1]) == 0) {
3840 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844
3845 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3846 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3847 file, linenum, args[0]);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
3851
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003852 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3853 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3854 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
3858
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003859 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003860
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003861 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003862 rule->cond = cond;
3863 rule->srv.name = strdup(args[1]);
3864 LIST_INIT(&rule->list);
3865 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3866 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3867 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003868 else if ((!strcmp(args[0], "force-persist")) ||
3869 (!strcmp(args[0], "ignore-persist"))) {
3870 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003871
3872 if (curproxy == &defproxy) {
3873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
3876 }
3877
3878 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3879 err_code |= ERR_WARN;
3880
Willy Tarreauef6494c2010-01-28 17:12:36 +01003881 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003882 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3883 file, linenum, args[0]);
3884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
3886 }
3887
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003888 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3889 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3890 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
3893 }
3894
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003895 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3896 * where force-persist is applied.
3897 */
3898 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003899
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003900 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003901 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003902 if (!strcmp(args[0], "force-persist")) {
3903 rule->type = PERSIST_TYPE_FORCE;
3904 } else {
3905 rule->type = PERSIST_TYPE_IGNORE;
3906 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003907 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003908 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003909 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003910 else if (!strcmp(args[0], "stick-table")) {
3911 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003912 struct proxy *other;
3913
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003914 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003915 if (other) {
3916 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3917 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
3920 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003921
Emeric Brun32da3c42010-09-23 18:39:19 +02003922 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003923 curproxy->table.type = (unsigned int)-1;
3924 while (*args[myidx]) {
3925 const char *err;
3926
3927 if (strcmp(args[myidx], "size") == 0) {
3928 myidx++;
3929 if (!*(args[myidx])) {
3930 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3931 file, linenum, args[myidx-1]);
3932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
3934 }
3935 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3936 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3937 file, linenum, *err, args[myidx-1]);
3938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
3940 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003941 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003942 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003943 else if (strcmp(args[myidx], "peers") == 0) {
3944 myidx++;
Godbach50523162013-12-11 19:48:57 +08003945 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003946 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3947 file, linenum, args[myidx-1]);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Godbach50523162013-12-11 19:48:57 +08003950 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003951 curproxy->table.peers.name = strdup(args[myidx++]);
3952 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003953 else if (strcmp(args[myidx], "expire") == 0) {
3954 myidx++;
3955 if (!*(args[myidx])) {
3956 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3957 file, linenum, args[myidx-1]);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
3961 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3962 if (err) {
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 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003968 if (val > INT_MAX) {
3969 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3970 file, linenum, val);
3971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
3973 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003974 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003975 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003976 }
3977 else if (strcmp(args[myidx], "nopurge") == 0) {
3978 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003979 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003980 }
3981 else if (strcmp(args[myidx], "type") == 0) {
3982 myidx++;
3983 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3984 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3985 file, linenum, args[myidx]);
3986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
3988 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003989 /* myidx already points to next arg */
3990 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003991 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003992 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003993 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003994
3995 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003996 nw = args[myidx];
3997 while (*nw) {
3998 /* the "store" keyword supports a comma-separated list */
3999 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004000 sa = NULL; /* store arg */
4001 while (*nw && *nw != ',') {
4002 if (*nw == '(') {
4003 *nw = 0;
4004 sa = ++nw;
4005 while (*nw != ')') {
4006 if (!*nw) {
4007 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4008 file, linenum, args[0], cw);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
4012 nw++;
4013 }
4014 *nw = '\0';
4015 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004016 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004017 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004018 if (*nw)
4019 *nw++ = '\0';
4020 type = stktable_get_data_type(cw);
4021 if (type < 0) {
4022 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4023 file, linenum, args[0], cw);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
Willy Tarreauac782882010-06-20 10:41:54 +02004027
4028 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4029 switch (err) {
4030 case PE_NONE: break;
4031 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004032 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4033 file, linenum, args[0], cw);
4034 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004035 break;
4036
4037 case PE_ARG_MISSING:
4038 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4039 file, linenum, args[0], cw);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042
4043 case PE_ARG_NOT_USED:
4044 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4045 file, linenum, args[0], cw);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048
4049 default:
4050 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4051 file, linenum, args[0], cw);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004054 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004055 }
4056 myidx++;
4057 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004058 else {
4059 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4060 file, linenum, args[myidx]);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004063 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004064 }
4065
4066 if (!curproxy->table.size) {
4067 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4068 file, linenum);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072
4073 if (curproxy->table.type == (unsigned int)-1) {
4074 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4075 file, linenum);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079 }
4080 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004081 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004082 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004083 int myidx = 0;
4084 const char *name = NULL;
4085 int flags;
4086
4087 if (curproxy == &defproxy) {
4088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091 }
4092
4093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4094 err_code |= ERR_WARN;
4095 goto out;
4096 }
4097
4098 myidx++;
4099 if ((strcmp(args[myidx], "store") == 0) ||
4100 (strcmp(args[myidx], "store-request") == 0)) {
4101 myidx++;
4102 flags = STK_IS_STORE;
4103 }
4104 else if (strcmp(args[myidx], "store-response") == 0) {
4105 myidx++;
4106 flags = STK_IS_STORE | STK_ON_RSP;
4107 }
4108 else if (strcmp(args[myidx], "match") == 0) {
4109 myidx++;
4110 flags = STK_IS_MATCH;
4111 }
4112 else if (strcmp(args[myidx], "on") == 0) {
4113 myidx++;
4114 flags = STK_IS_MATCH | STK_IS_STORE;
4115 }
4116 else {
4117 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121
4122 if (*(args[myidx]) == 0) {
4123 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004128 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004129 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004130 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004131 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
4135
4136 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004137 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4138 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4139 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004140 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004141 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004142 goto out;
4143 }
4144 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004145 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4146 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4147 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004148 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004149 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 goto out;
4151 }
4152 }
4153
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004154 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004155 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004156
Emeric Brunb982a3d2010-01-04 15:45:53 +01004157 if (strcmp(args[myidx], "table") == 0) {
4158 myidx++;
4159 name = args[myidx++];
4160 }
4161
Willy Tarreauef6494c2010-01-28 17:12:36 +01004162 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004163 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4164 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4165 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004166 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004167 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004168 goto out;
4169 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004170 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004171 else if (*(args[myidx])) {
4172 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4173 file, linenum, args[0], args[myidx]);
4174 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004175 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004176 goto out;
4177 }
Emeric Brun97679e72010-09-23 17:56:44 +02004178 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004179 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004180 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004181 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004182
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004183 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004184 rule->cond = cond;
4185 rule->expr = expr;
4186 rule->flags = flags;
4187 rule->table.name = name ? strdup(name) : NULL;
4188 LIST_INIT(&rule->list);
4189 if (flags & STK_ON_RSP)
4190 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4191 else
4192 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 else if (!strcmp(args[0], "stats")) {
4195 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4196 curproxy->uri_auth = NULL; /* we must detach from the default config */
4197
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004198 if (!*args[1]) {
4199 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004200 } else if (!strcmp(args[1], "admin")) {
4201 struct stats_admin_rule *rule;
4202
4203 if (curproxy == &defproxy) {
4204 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
4207 }
4208
4209 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4210 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4211 err_code |= ERR_ALERT | ERR_ABORT;
4212 goto out;
4213 }
4214
4215 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4216 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4217 file, linenum, args[0], args[1]);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004221 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4222 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4223 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
4226 }
4227
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004228 err_code |= warnif_cond_conflicts(cond,
4229 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4230 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004231
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004232 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004233 rule->cond = cond;
4234 LIST_INIT(&rule->list);
4235 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004236 } else if (!strcmp(args[1], "uri")) {
4237 if (*(args[2]) == 0) {
4238 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4242 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004243 err_code |= ERR_ALERT | ERR_ABORT;
4244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 }
4246 } else if (!strcmp(args[1], "realm")) {
4247 if (*(args[2]) == 0) {
4248 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4252 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_ABORT;
4254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004256 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004257 unsigned interval;
4258
4259 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4260 if (err) {
4261 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4262 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004265 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4266 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004267 err_code |= ERR_ALERT | ERR_ABORT;
4268 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004269 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004270 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004271 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004272
4273 if (curproxy == &defproxy) {
4274 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
4278
4279 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4280 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4281 err_code |= ERR_ALERT | ERR_ABORT;
4282 goto out;
4283 }
4284
Willy Tarreauff011f22011-01-06 17:51:27 +01004285 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004286 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004287 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4288 file, linenum, args[0]);
4289 err_code |= ERR_WARN;
4290 }
4291
Willy Tarreauff011f22011-01-06 17:51:27 +01004292 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004293
Willy Tarreauff011f22011-01-06 17:51:27 +01004294 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004295 err_code |= ERR_ALERT | ERR_ABORT;
4296 goto out;
4297 }
4298
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004299 err_code |= warnif_cond_conflicts(rule->cond,
4300 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4301 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004302 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004303
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 } else if (!strcmp(args[1], "auth")) {
4305 if (*(args[2]) == 0) {
4306 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4310 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004311 err_code |= ERR_ALERT | ERR_ABORT;
4312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004313 }
4314 } else if (!strcmp(args[1], "scope")) {
4315 if (*(args[2]) == 0) {
4316 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004317 err_code |= ERR_ALERT | ERR_FATAL;
4318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4320 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_ABORT;
4322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 }
4324 } else if (!strcmp(args[1], "enable")) {
4325 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4326 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_ABORT;
4328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004330 } else if (!strcmp(args[1], "hide-version")) {
4331 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4332 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_ABORT;
4334 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004335 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004336 } else if (!strcmp(args[1], "show-legends")) {
4337 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4338 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4339 err_code |= ERR_ALERT | ERR_ABORT;
4340 goto out;
4341 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004342 } else if (!strcmp(args[1], "show-node")) {
4343
4344 if (*args[2]) {
4345 int i;
4346 char c;
4347
4348 for (i=0; args[2][i]; i++) {
4349 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004350 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4351 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004352 break;
4353 }
4354
4355 if (!i || args[2][i]) {
4356 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4357 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4358 file, linenum, args[0], args[1]);
4359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
4361 }
4362 }
4363
4364 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4365 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4366 err_code |= ERR_ALERT | ERR_ABORT;
4367 goto out;
4368 }
4369 } else if (!strcmp(args[1], "show-desc")) {
4370 char *desc = NULL;
4371
4372 if (*args[2]) {
4373 int i, len=0;
4374 char *d;
4375
Willy Tarreau348acfe2014-04-14 15:00:39 +02004376 for (i = 2; *args[i]; i++)
4377 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004378
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004379 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004380
Willy Tarreau348acfe2014-04-14 15:00:39 +02004381 d += snprintf(d, desc + len - d, "%s", args[2]);
4382 for (i = 3; *args[i]; i++)
4383 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004384 }
4385
4386 if (!*args[2] && !global.desc)
4387 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4388 file, linenum, args[1]);
4389 else {
4390 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4391 free(desc);
4392 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4393 err_code |= ERR_ALERT | ERR_ABORT;
4394 goto out;
4395 }
4396 free(desc);
4397 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004399stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004400 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 +01004401 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 }
4405 }
4406 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004407 int optnum;
4408
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004409 if (*(args[1]) == '\0') {
4410 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4411 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004415
4416 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4417 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004418 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4419 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4420 file, linenum, cfg_opts[optnum].name);
4421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
4423 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004424 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4425 goto out;
4426
Willy Tarreau93893792009-07-23 13:19:11 +02004427 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4428 err_code |= ERR_WARN;
4429 goto out;
4430 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004431
Willy Tarreau3842f002009-06-14 11:39:52 +02004432 curproxy->no_options &= ~cfg_opts[optnum].val;
4433 curproxy->options &= ~cfg_opts[optnum].val;
4434
4435 switch (kwm) {
4436 case KWM_STD:
4437 curproxy->options |= cfg_opts[optnum].val;
4438 break;
4439 case KWM_NO:
4440 curproxy->no_options |= cfg_opts[optnum].val;
4441 break;
4442 case KWM_DEF: /* already cleared */
4443 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004444 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004445
Willy Tarreau93893792009-07-23 13:19:11 +02004446 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004447 }
4448 }
4449
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004450 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4451 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004452 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4453 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4454 file, linenum, cfg_opts2[optnum].name);
4455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
4457 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004458 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4459 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004460 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4461 err_code |= ERR_WARN;
4462 goto out;
4463 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004464
Willy Tarreau3842f002009-06-14 11:39:52 +02004465 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4466 curproxy->options2 &= ~cfg_opts2[optnum].val;
4467
4468 switch (kwm) {
4469 case KWM_STD:
4470 curproxy->options2 |= cfg_opts2[optnum].val;
4471 break;
4472 case KWM_NO:
4473 curproxy->no_options2 |= cfg_opts2[optnum].val;
4474 break;
4475 case KWM_DEF: /* already cleared */
4476 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004477 }
Willy Tarreau93893792009-07-23 13:19:11 +02004478 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004479 }
4480 }
4481
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004482 /* HTTP options override each other. They can be cancelled using
4483 * "no option xxx" which only switches to default mode if the mode
4484 * was this one (useful for cancelling options set in defaults
4485 * sections).
4486 */
4487 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004488 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4489 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004490 if (kwm == KWM_STD) {
4491 curproxy->options &= ~PR_O_HTTP_MODE;
4492 curproxy->options |= PR_O_HTTP_PCL;
4493 goto out;
4494 }
4495 else if (kwm == KWM_NO) {
4496 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4497 curproxy->options &= ~PR_O_HTTP_MODE;
4498 goto out;
4499 }
4500 }
4501 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004502 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4503 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004504 if (kwm == KWM_STD) {
4505 curproxy->options &= ~PR_O_HTTP_MODE;
4506 curproxy->options |= PR_O_HTTP_FCL;
4507 goto out;
4508 }
4509 else if (kwm == KWM_NO) {
4510 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4511 curproxy->options &= ~PR_O_HTTP_MODE;
4512 goto out;
4513 }
4514 }
4515 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004516 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4517 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004518 if (kwm == KWM_STD) {
4519 curproxy->options &= ~PR_O_HTTP_MODE;
4520 curproxy->options |= PR_O_HTTP_SCL;
4521 goto out;
4522 }
4523 else if (kwm == KWM_NO) {
4524 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4525 curproxy->options &= ~PR_O_HTTP_MODE;
4526 goto out;
4527 }
4528 }
4529 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004530 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4531 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004532 if (kwm == KWM_STD) {
4533 curproxy->options &= ~PR_O_HTTP_MODE;
4534 curproxy->options |= PR_O_HTTP_KAL;
4535 goto out;
4536 }
4537 else if (kwm == KWM_NO) {
4538 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4539 curproxy->options &= ~PR_O_HTTP_MODE;
4540 goto out;
4541 }
4542 }
4543 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004544 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4545 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004546 if (kwm == KWM_STD) {
4547 curproxy->options &= ~PR_O_HTTP_MODE;
4548 curproxy->options |= PR_O_HTTP_TUN;
4549 goto out;
4550 }
4551 else if (kwm == KWM_NO) {
4552 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4553 curproxy->options &= ~PR_O_HTTP_MODE;
4554 goto out;
4555 }
4556 }
4557
Joseph Lynch726ab712015-05-11 23:25:34 -07004558 /* Redispatch can take an integer argument that control when the
4559 * resispatch occurs. All values are relative to the retries option.
4560 * This can be cancelled using "no option xxx".
4561 */
4562 if (strcmp(args[1], "redispatch") == 0) {
4563 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4564 err_code |= ERR_WARN;
4565 goto out;
4566 }
4567
4568 curproxy->no_options &= ~PR_O_REDISP;
4569 curproxy->options &= ~PR_O_REDISP;
4570
4571 switch (kwm) {
4572 case KWM_STD:
4573 curproxy->options |= PR_O_REDISP;
4574 curproxy->redispatch_after = -1;
4575 if(*args[2]) {
4576 curproxy->redispatch_after = atol(args[2]);
4577 }
4578 break;
4579 case KWM_NO:
4580 curproxy->no_options |= PR_O_REDISP;
4581 curproxy->redispatch_after = 0;
4582 break;
4583 case KWM_DEF: /* already cleared */
4584 break;
4585 }
4586 goto out;
4587 }
4588
Willy Tarreau3842f002009-06-14 11:39:52 +02004589 if (kwm != KWM_STD) {
4590 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004591 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004594 }
4595
Emeric Brun3a058f32009-06-30 18:26:00 +02004596 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004597 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004599 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004600 if (*(args[2]) != '\0') {
4601 if (!strcmp(args[2], "clf")) {
4602 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004603 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004604 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004605 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004606 err_code |= ERR_ALERT | ERR_FATAL;
4607 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004608 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004609 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4610 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004611 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004612 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4613 char *oldlogformat = "log-format";
4614 char *clflogformat = "";
4615
4616 if (curproxy->conf.logformat_string == default_http_log_format)
4617 oldlogformat = "option httplog";
4618 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4619 oldlogformat = "option tcplog";
4620 else if (curproxy->conf.logformat_string == clf_http_log_format)
4621 oldlogformat = "option httplog clf";
4622 if (logformat == clf_http_log_format)
4623 clflogformat = " clf";
4624 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4625 file, linenum, clflogformat, oldlogformat);
4626 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004627 if (curproxy->conf.logformat_string != default_http_log_format &&
4628 curproxy->conf.logformat_string != default_tcp_log_format &&
4629 curproxy->conf.logformat_string != clf_http_log_format)
4630 free(curproxy->conf.logformat_string);
4631 curproxy->conf.logformat_string = logformat;
4632
4633 free(curproxy->conf.lfs_file);
4634 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4635 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004636 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004637 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004638 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4639 char *oldlogformat = "log-format";
4640
4641 if (curproxy->conf.logformat_string == default_http_log_format)
4642 oldlogformat = "option httplog";
4643 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4644 oldlogformat = "option tcplog";
4645 else if (curproxy->conf.logformat_string == clf_http_log_format)
4646 oldlogformat = "option httplog clf";
4647 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4648 file, linenum, oldlogformat);
4649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004651 if (curproxy->conf.logformat_string != default_http_log_format &&
4652 curproxy->conf.logformat_string != default_tcp_log_format &&
4653 curproxy->conf.logformat_string != clf_http_log_format)
4654 free(curproxy->conf.logformat_string);
4655 curproxy->conf.logformat_string = default_tcp_log_format;
4656
4657 free(curproxy->conf.lfs_file);
4658 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4659 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004660
4661 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4662 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004665 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004666 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004668
William Lallemanddf1425a2015-04-28 20:17:49 +02004669 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4670 goto out;
4671
Willy Tarreau13943ab2006-12-31 00:24:10 +01004672 if (curproxy->cap & PR_CAP_FE)
4673 curproxy->options |= PR_O_TCP_CLI_KA;
4674 if (curproxy->cap & PR_CAP_BE)
4675 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 }
4677 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004678 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004679 err_code |= ERR_WARN;
4680
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004682 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004683 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004684 curproxy->options2 &= ~PR_O2_CHK_ANY;
4685 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 if (!*args[2]) { /* no argument */
4687 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4688 curproxy->check_len = strlen(DEF_CHECK_REQ);
4689 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004690 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004691 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004693 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004695 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696 if (*args[4])
4697 reqlen += strlen(args[4]);
4698 else
4699 reqlen += strlen("HTTP/1.0");
4700
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004701 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004703 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004705 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4706 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004707 }
4708 else if (!strcmp(args[1], "ssl-hello-chk")) {
4709 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004711 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004712
Willy Tarreaua534fea2008-08-03 12:19:50 +02004713 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004714 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004715 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004716 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004717
4718 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720 }
Willy Tarreau23677902007-05-08 23:50:35 +02004721 else if (!strcmp(args[1], "smtpchk")) {
4722 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004723 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004724 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004725 curproxy->options2 &= ~PR_O2_CHK_ANY;
4726 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004727
4728 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4729 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4730 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4731 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4732 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4733 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004734 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004735 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4736 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4737 } else {
4738 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4739 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4740 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4741 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4742 }
4743 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004744 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4745 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004746 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004747 else if (!strcmp(args[1], "pgsql-check")) {
4748 /* use PostgreSQL request to check servers' health */
4749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4750 err_code |= ERR_WARN;
4751
4752 free(curproxy->check_req);
4753 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004754 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004755 curproxy->options2 |= PR_O2_PGSQL_CHK;
4756
4757 if (*(args[2])) {
4758 int cur_arg = 2;
4759
4760 while (*(args[cur_arg])) {
4761 if (strcmp(args[cur_arg], "user") == 0) {
4762 char * packet;
4763 uint32_t packet_len;
4764 uint32_t pv;
4765
4766 /* suboption header - needs additional argument for it */
4767 if (*(args[cur_arg+1]) == 0) {
4768 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4769 file, linenum, args[0], args[1], args[cur_arg]);
4770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
4773
4774 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4775 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4776 pv = htonl(0x30000); /* protocol version 3.0 */
4777
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004778 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004779
4780 memcpy(packet + 4, &pv, 4);
4781
4782 /* copy "user" */
4783 memcpy(packet + 8, "user", 4);
4784
4785 /* copy username */
4786 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4787
4788 free(curproxy->check_req);
4789 curproxy->check_req = packet;
4790 curproxy->check_len = packet_len;
4791
4792 packet_len = htonl(packet_len);
4793 memcpy(packet, &packet_len, 4);
4794 cur_arg += 2;
4795 } else {
4796 /* unknown suboption - catchall */
4797 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4798 file, linenum, args[0], args[1]);
4799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
4802 } /* end while loop */
4803 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004804 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4805 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004806 }
4807
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004808 else if (!strcmp(args[1], "redis-check")) {
4809 /* use REDIS PING request to check servers' health */
4810 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4811 err_code |= ERR_WARN;
4812
4813 free(curproxy->check_req);
4814 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004815 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004816 curproxy->options2 |= PR_O2_REDIS_CHK;
4817
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004818 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004819 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4820 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004821
4822 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4823 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004824 }
4825
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004826 else if (!strcmp(args[1], "mysql-check")) {
4827 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004828 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4829 err_code |= ERR_WARN;
4830
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004831 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004832 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004833 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004834 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004835
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004836 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004837 * const char mysql40_client_auth_pkt[] = {
4838 * "\x0e\x00\x00" // packet length
4839 * "\x01" // packet number
4840 * "\x00\x00" // client capabilities
4841 * "\x00\x00\x01" // max packet
4842 * "haproxy\x00" // username (null terminated string)
4843 * "\x00" // filler (always 0x00)
4844 * "\x01\x00\x00" // packet length
4845 * "\x00" // packet number
4846 * "\x01" // COM_QUIT command
4847 * };
4848 */
4849
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004850 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4851 * const char mysql41_client_auth_pkt[] = {
4852 * "\x0e\x00\x00\" // packet length
4853 * "\x01" // packet number
4854 * "\x00\x00\x00\x00" // client capabilities
4855 * "\x00\x00\x00\x01" // max packet
4856 * "\x21" // character set (UTF-8)
4857 * char[23] // All zeroes
4858 * "haproxy\x00" // username (null terminated string)
4859 * "\x00" // filler (always 0x00)
4860 * "\x01\x00\x00" // packet length
4861 * "\x00" // packet number
4862 * "\x01" // COM_QUIT command
4863 * };
4864 */
4865
4866
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004867 if (*(args[2])) {
4868 int cur_arg = 2;
4869
4870 while (*(args[cur_arg])) {
4871 if (strcmp(args[cur_arg], "user") == 0) {
4872 char *mysqluser;
4873 int packetlen, reqlen, userlen;
4874
4875 /* suboption header - needs additional argument for it */
4876 if (*(args[cur_arg+1]) == 0) {
4877 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4878 file, linenum, args[0], args[1], args[cur_arg]);
4879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
4881 }
4882 mysqluser = args[cur_arg + 1];
4883 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004884
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004885 if (*(args[cur_arg+2])) {
4886 if (!strcmp(args[cur_arg+2], "post-41")) {
4887 packetlen = userlen + 7 + 27;
4888 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004889
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004890 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004891 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004892 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004893
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004894 snprintf(curproxy->check_req, 4, "%c%c%c",
4895 ((unsigned char) packetlen & 0xff),
4896 ((unsigned char) (packetlen >> 8) & 0xff),
4897 ((unsigned char) (packetlen >> 16) & 0xff));
4898
4899 curproxy->check_req[3] = 1;
4900 curproxy->check_req[5] = 130;
4901 curproxy->check_req[11] = 1;
4902 curproxy->check_req[12] = 33;
4903 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4904 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4905 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4906 cur_arg += 3;
4907 } else {
4908 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
4911 }
4912 } else {
4913 packetlen = userlen + 7;
4914 reqlen = packetlen + 9;
4915
4916 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004917 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004918 curproxy->check_len = reqlen;
4919
4920 snprintf(curproxy->check_req, 4, "%c%c%c",
4921 ((unsigned char) packetlen & 0xff),
4922 ((unsigned char) (packetlen >> 8) & 0xff),
4923 ((unsigned char) (packetlen >> 16) & 0xff));
4924
4925 curproxy->check_req[3] = 1;
4926 curproxy->check_req[5] = 128;
4927 curproxy->check_req[8] = 1;
4928 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4929 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4930 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4931 cur_arg += 2;
4932 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004933 } else {
4934 /* unknown suboption - catchall */
4935 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4936 file, linenum, args[0], args[1]);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
4940 } /* end while loop */
4941 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004942 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004943 else if (!strcmp(args[1], "ldap-check")) {
4944 /* use LDAP request to check servers' health */
4945 free(curproxy->check_req);
4946 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004947 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004948 curproxy->options2 |= PR_O2_LDAP_CHK;
4949
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004950 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004951 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4952 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004953 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4954 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004955 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004956 else if (!strcmp(args[1], "spop-check")) {
4957 if (curproxy == &defproxy) {
4958 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4959 file, linenum, args[0], args[1]);
4960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
4962 }
4963 if (curproxy->cap & PR_CAP_FE) {
4964 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4965 file, linenum, args[0], args[1]);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
4969
4970 /* use SPOE request to check servers' health */
4971 free(curproxy->check_req);
4972 curproxy->check_req = NULL;
4973 curproxy->options2 &= ~PR_O2_CHK_ANY;
4974 curproxy->options2 |= PR_O2_SPOP_CHK;
4975
Christopher Faulet8ef75252017-02-20 22:56:03 +01004976 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01004977 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4982 goto out;
4983 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004984 else if (!strcmp(args[1], "tcp-check")) {
4985 /* use raw TCPCHK send/expect to check servers' health */
4986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4987 err_code |= ERR_WARN;
4988
4989 free(curproxy->check_req);
4990 curproxy->check_req = NULL;
4991 curproxy->options2 &= ~PR_O2_CHK_ANY;
4992 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004993 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4994 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004995 }
Simon Horman98637e52014-06-20 12:30:16 +09004996 else if (!strcmp(args[1], "external-check")) {
4997 /* excute an external command 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_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005002 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5003 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005004 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005005 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005006 int cur_arg;
5007
5008 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5009 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005010 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005011
Willy Tarreau87cf5142011-08-19 22:57:24 +02005012 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005013
5014 free(curproxy->fwdfor_hdr_name);
5015 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5016 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5017
5018 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5019 cur_arg = 2;
5020 while (*(args[cur_arg])) {
5021 if (!strcmp(args[cur_arg], "except")) {
5022 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005023 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005024 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5025 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005028 }
5029 /* flush useless bits */
5030 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005031 cur_arg += 2;
5032 } else if (!strcmp(args[cur_arg], "header")) {
5033 /* suboption header - needs additional argument for it */
5034 if (*(args[cur_arg+1]) == 0) {
5035 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5036 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005039 }
5040 free(curproxy->fwdfor_hdr_name);
5041 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5042 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5043 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005044 } else if (!strcmp(args[cur_arg], "if-none")) {
5045 curproxy->options &= ~PR_O_FF_ALWAYS;
5046 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005047 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005048 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005049 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005050 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005053 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005054 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005055 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005056 else if (!strcmp(args[1], "originalto")) {
5057 int cur_arg;
5058
5059 /* insert x-original-to field, but not for the IP address listed as an except.
5060 * set default options (ie: bitfield, header name, etc)
5061 */
5062
5063 curproxy->options |= PR_O_ORGTO;
5064
5065 free(curproxy->orgto_hdr_name);
5066 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5067 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5068
Willy Tarreau87cf5142011-08-19 22:57:24 +02005069 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005070 cur_arg = 2;
5071 while (*(args[cur_arg])) {
5072 if (!strcmp(args[cur_arg], "except")) {
5073 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005074 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 +02005075 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5076 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005079 }
5080 /* flush useless bits */
5081 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5082 cur_arg += 2;
5083 } else if (!strcmp(args[cur_arg], "header")) {
5084 /* suboption header - needs additional argument for it */
5085 if (*(args[cur_arg+1]) == 0) {
5086 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5087 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005090 }
5091 free(curproxy->orgto_hdr_name);
5092 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5093 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5094 cur_arg += 2;
5095 } else {
5096 /* unknown suboption - catchall */
5097 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5098 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005101 }
5102 } /* end while loop */
5103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 else {
5105 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 }
Willy Tarreau93893792009-07-23 13:19:11 +02005109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005111 else if (!strcmp(args[0], "default_backend")) {
5112 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005114
5115 if (*(args[1]) == 0) {
5116 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005119 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005120 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005121 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005122
5123 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5124 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005127 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005128 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005129
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005130 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5131 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 +01005132 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005133 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 /* enable reconnections to dispatch */
5135 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005136
5137 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005140 else if (!strcmp(args[0], "http-reuse")) {
5141 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5142 err_code |= ERR_WARN;
5143
5144 if (strcmp(args[1], "never") == 0) {
5145 /* enable a graceful server shutdown on an HTTP 404 response */
5146 curproxy->options &= ~PR_O_REUSE_MASK;
5147 curproxy->options |= PR_O_REUSE_NEVR;
5148 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5149 goto out;
5150 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005151 else if (strcmp(args[1], "safe") == 0) {
5152 /* enable a graceful server shutdown on an HTTP 404 response */
5153 curproxy->options &= ~PR_O_REUSE_MASK;
5154 curproxy->options |= PR_O_REUSE_SAFE;
5155 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5156 goto out;
5157 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005158 else if (strcmp(args[1], "aggressive") == 0) {
5159 curproxy->options &= ~PR_O_REUSE_MASK;
5160 curproxy->options |= PR_O_REUSE_AGGR;
5161 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5162 goto out;
5163 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005164 else if (strcmp(args[1], "always") == 0) {
5165 /* enable a graceful server shutdown on an HTTP 404 response */
5166 curproxy->options &= ~PR_O_REUSE_MASK;
5167 curproxy->options |= PR_O_REUSE_ALWS;
5168 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5169 goto out;
5170 }
5171 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005172 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005173 err_code |= ERR_ALERT | ERR_FATAL;
5174 goto out;
5175 }
5176 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005177 else if (!strcmp(args[0], "http-check")) {
5178 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005179 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005180
5181 if (strcmp(args[1], "disable-on-404") == 0) {
5182 /* enable a graceful server shutdown on an HTTP 404 response */
5183 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005184 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5185 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005186 }
Willy Tarreauef781042010-01-27 11:53:01 +01005187 else if (strcmp(args[1], "send-state") == 0) {
5188 /* enable emission of the apparent state of a server in HTTP checks */
5189 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005190 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5191 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005192 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005193 else if (strcmp(args[1], "expect") == 0) {
5194 const char *ptr_arg;
5195 int cur_arg;
5196
5197 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5198 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
5201 }
5202
5203 cur_arg = 2;
5204 /* consider exclamation marks, sole or at the beginning of a word */
5205 while (*(ptr_arg = args[cur_arg])) {
5206 while (*ptr_arg == '!') {
5207 curproxy->options2 ^= PR_O2_EXP_INV;
5208 ptr_arg++;
5209 }
5210 if (*ptr_arg)
5211 break;
5212 cur_arg++;
5213 }
5214 /* now ptr_arg points to the beginning of a word past any possible
5215 * exclamation mark, and cur_arg is the argument which holds this word.
5216 */
5217 if (strcmp(ptr_arg, "status") == 0) {
5218 if (!*(args[cur_arg + 1])) {
5219 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5220 file, linenum, args[0], args[1], ptr_arg);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
5224 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005225 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005226 curproxy->expect_str = strdup(args[cur_arg + 1]);
5227 }
5228 else if (strcmp(ptr_arg, "string") == 0) {
5229 if (!*(args[cur_arg + 1])) {
5230 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5231 file, linenum, args[0], args[1], ptr_arg);
5232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
5234 }
5235 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005236 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005237 curproxy->expect_str = strdup(args[cur_arg + 1]);
5238 }
5239 else if (strcmp(ptr_arg, "rstatus") == 0) {
5240 if (!*(args[cur_arg + 1])) {
5241 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5242 file, linenum, args[0], args[1], ptr_arg);
5243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245 }
5246 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005247 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005248 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005249 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005250 free(curproxy->expect_regex);
5251 curproxy->expect_regex = NULL;
5252 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005253 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005254 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5255 error = NULL;
5256 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5257 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5258 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5259 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 }
5263 }
5264 else if (strcmp(ptr_arg, "rstring") == 0) {
5265 if (!*(args[cur_arg + 1])) {
5266 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5267 file, linenum, args[0], args[1], ptr_arg);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005272 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005273 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005274 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005275 free(curproxy->expect_regex);
5276 curproxy->expect_regex = NULL;
5277 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005278 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005279 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5280 error = NULL;
5281 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5282 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5283 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5284 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
5287 }
5288 }
5289 else {
5290 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5291 file, linenum, args[0], args[1], ptr_arg);
5292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
5294 }
5295 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005296 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005297 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 +02005298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005300 }
5301 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005302 else if (!strcmp(args[0], "tcp-check")) {
5303 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5304 err_code |= ERR_WARN;
5305
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005306 if (strcmp(args[1], "comment") == 0) {
5307 int cur_arg;
5308 struct tcpcheck_rule *tcpcheck;
5309
5310 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005311 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005312 tcpcheck->action = TCPCHK_ACT_COMMENT;
5313
5314 if (!*args[cur_arg + 1]) {
5315 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5316 file, linenum, args[cur_arg]);
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320
5321 tcpcheck->comment = strdup(args[cur_arg + 1]);
5322
5323 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005324 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5325 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005326 }
5327 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005328 const char *ptr_arg;
5329 int cur_arg;
5330 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005331
5332 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005333 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5334 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5335 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5336 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5337 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005338
Willy Tarreau5581c272015-05-13 12:24:53 +02005339 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5340 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5341 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5342 file, linenum);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005345 }
5346
5347 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005348 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005349 tcpcheck->action = TCPCHK_ACT_CONNECT;
5350
5351 /* parsing each parameters to fill up the rule */
5352 while (*(ptr_arg = args[cur_arg])) {
5353 /* tcp port */
5354 if (strcmp(args[cur_arg], "port") == 0) {
5355 if ( (atol(args[cur_arg + 1]) > 65535) ||
5356 (atol(args[cur_arg + 1]) < 1) ){
5357 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5358 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 }
5362 tcpcheck->port = atol(args[cur_arg + 1]);
5363 cur_arg += 2;
5364 }
5365 /* send proxy protocol */
5366 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5367 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5368 cur_arg++;
5369 }
5370#ifdef USE_OPENSSL
5371 else if (strcmp(args[cur_arg], "ssl") == 0) {
5372 curproxy->options |= PR_O_TCPCHK_SSL;
5373 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5374 cur_arg++;
5375 }
5376#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005377 /* comment for this tcpcheck line */
5378 else if (strcmp(args[cur_arg], "comment") == 0) {
5379 if (!*args[cur_arg + 1]) {
5380 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5381 file, linenum, args[cur_arg]);
5382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
5384 }
5385 tcpcheck->comment = strdup(args[cur_arg + 1]);
5386 cur_arg += 2;
5387 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005388 else {
5389#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005390 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 +01005391#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005392 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 +01005393#endif /* USE_OPENSSL */
5394 file, linenum, args[0], args[1], args[cur_arg]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398
5399 }
5400
5401 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5402 }
5403 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005404 if (! *(args[2]) ) {
5405 /* SEND string expected */
5406 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5407 file, linenum, args[0], args[1], args[2]);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 } else {
5411 struct tcpcheck_rule *tcpcheck;
5412
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005413 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005414
5415 tcpcheck->action = TCPCHK_ACT_SEND;
5416 tcpcheck->string_len = strlen(args[2]);
5417 tcpcheck->string = strdup(args[2]);
5418 tcpcheck->expect_regex = NULL;
5419
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005420 /* comment for this tcpcheck line */
5421 if (strcmp(args[3], "comment") == 0) {
5422 if (!*args[4]) {
5423 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5424 file, linenum, args[3]);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
5428 tcpcheck->comment = strdup(args[4]);
5429 }
5430
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005431 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5432 }
5433 }
5434 else if (strcmp(args[1], "send-binary") == 0) {
5435 if (! *(args[2]) ) {
5436 /* SEND binary string expected */
5437 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5438 file, linenum, args[0], args[1], args[2]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 } else {
5442 struct tcpcheck_rule *tcpcheck;
5443 char *err = NULL;
5444
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005445 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005446
5447 tcpcheck->action = TCPCHK_ACT_SEND;
5448 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5449 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5450 file, linenum, args[0], args[1], args[2], err);
5451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
5454 tcpcheck->expect_regex = NULL;
5455
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005456 /* comment for this tcpcheck line */
5457 if (strcmp(args[3], "comment") == 0) {
5458 if (!*args[4]) {
5459 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5460 file, linenum, args[3]);
5461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
5463 }
5464 tcpcheck->comment = strdup(args[4]);
5465 }
5466
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005467 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5468 }
5469 }
5470 else if (strcmp(args[1], "expect") == 0) {
5471 const char *ptr_arg;
5472 int cur_arg;
5473 int inverse = 0;
5474
5475 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5476 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480
5481 cur_arg = 2;
5482 /* consider exclamation marks, sole or at the beginning of a word */
5483 while (*(ptr_arg = args[cur_arg])) {
5484 while (*ptr_arg == '!') {
5485 inverse = !inverse;
5486 ptr_arg++;
5487 }
5488 if (*ptr_arg)
5489 break;
5490 cur_arg++;
5491 }
5492 /* now ptr_arg points to the beginning of a word past any possible
5493 * exclamation mark, and cur_arg is the argument which holds this word.
5494 */
5495 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005496 struct tcpcheck_rule *tcpcheck;
5497 char *err = NULL;
5498
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005499 if (!*(args[cur_arg + 1])) {
5500 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5501 file, linenum, args[0], args[1], ptr_arg);
5502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
5504 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005505
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005506 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005507
5508 tcpcheck->action = TCPCHK_ACT_EXPECT;
5509 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5510 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5511 file, linenum, args[0], args[1], args[2], err);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515 tcpcheck->expect_regex = NULL;
5516 tcpcheck->inverse = inverse;
5517
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005518 /* tcpcheck comment */
5519 cur_arg += 2;
5520 if (strcmp(args[cur_arg], "comment") == 0) {
5521 if (!*args[cur_arg + 1]) {
5522 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5523 file, linenum, args[cur_arg + 1]);
5524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526 }
5527 tcpcheck->comment = strdup(args[cur_arg + 1]);
5528 }
5529
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005530 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5531 }
5532 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005533 struct tcpcheck_rule *tcpcheck;
5534
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005535 if (!*(args[cur_arg + 1])) {
5536 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5537 file, linenum, args[0], args[1], ptr_arg);
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005541
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005542 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005543
5544 tcpcheck->action = TCPCHK_ACT_EXPECT;
5545 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5546 tcpcheck->string = strdup(args[cur_arg + 1]);
5547 tcpcheck->expect_regex = NULL;
5548 tcpcheck->inverse = inverse;
5549
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005550 /* tcpcheck comment */
5551 cur_arg += 2;
5552 if (strcmp(args[cur_arg], "comment") == 0) {
5553 if (!*args[cur_arg + 1]) {
5554 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5555 file, linenum, args[cur_arg + 1]);
5556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
5558 }
5559 tcpcheck->comment = strdup(args[cur_arg + 1]);
5560 }
5561
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005562 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5563 }
5564 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005565 struct tcpcheck_rule *tcpcheck;
5566
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005567 if (!*(args[cur_arg + 1])) {
5568 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5569 file, linenum, args[0], args[1], ptr_arg);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005573
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005574 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005575
5576 tcpcheck->action = TCPCHK_ACT_EXPECT;
5577 tcpcheck->string_len = 0;
5578 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005579 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5580 error = NULL;
5581 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5582 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5583 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5584 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
5587 }
5588 tcpcheck->inverse = inverse;
5589
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005590 /* tcpcheck comment */
5591 cur_arg += 2;
5592 if (strcmp(args[cur_arg], "comment") == 0) {
5593 if (!*args[cur_arg + 1]) {
5594 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5595 file, linenum, args[cur_arg + 1]);
5596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
5598 }
5599 tcpcheck->comment = strdup(args[cur_arg + 1]);
5600 }
5601
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005602 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5603 }
5604 else {
5605 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5606 file, linenum, args[0], args[1], ptr_arg);
5607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
5609 }
5610 }
5611 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005612 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
5615 }
5616 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005617 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005618 if (curproxy == &defproxy) {
5619 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005622 }
5623
Willy Tarreaub80c2302007-11-30 20:51:32 +01005624 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005625 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005626
5627 if (strcmp(args[1], "fail") == 0) {
5628 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005629 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005630 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5631 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005634 }
5635
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005636 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5637 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5638 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005641 }
5642 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5643 }
5644 else {
5645 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005648 }
5649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650#ifdef TPROXY
5651 else if (!strcmp(args[0], "transparent")) {
5652 /* enable transparent proxy connections */
5653 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005654 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 }
5657#endif
5658 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005660 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005661
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 if (*(args[1]) == 0) {
5663 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005664 err_code |= ERR_ALERT | ERR_FATAL;
5665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 }
5667 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005668 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005671 else if (!strcmp(args[0], "backlog")) { /* backlog */
5672 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005674
5675 if (*(args[1]) == 0) {
5676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005679 }
5680 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005681 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5682 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005683 }
Willy Tarreau86034312006-12-29 00:10:33 +01005684 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005685 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005687
Willy Tarreau86034312006-12-29 00:10:33 +01005688 if (*(args[1]) == 0) {
5689 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005692 }
5693 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005694 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5695 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005696 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5698 if (*(args[1]) == 0) {
5699 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005703 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5704 if (err) {
5705 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5706 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005709 }
5710 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005711 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 }
5714 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005715 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005716 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005717 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005718
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 if (curproxy == &defproxy) {
5720 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005724 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005726
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005727 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005728 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005729 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005731 goto out;
5732 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005733
5734 proto = protocol_by_family(sk->ss_family);
5735 if (!proto || !proto->connect) {
5736 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5737 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
5740 }
5741
5742 if (port1 != port2) {
5743 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5744 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005747 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005748
5749 if (!port1) {
5750 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5751 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005752 err_code |= ERR_ALERT | ERR_FATAL;
5753 goto out;
5754 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005755
William Lallemanddf1425a2015-04-28 20:17:49 +02005756 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5757 goto out;
5758
Willy Tarreaud5191e72010-02-09 20:50:45 +01005759 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005760 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 }
5762 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005763 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005765
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005766 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5767 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005772 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005773 /**
5774 * The syntax for hash-type config element is
5775 * hash-type {map-based|consistent} [[<algo>] avalanche]
5776 *
5777 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5778 */
5779 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005780
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005781 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5782 err_code |= ERR_WARN;
5783
5784 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005785 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5786 }
5787 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005788 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5789 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005790 else if (strcmp(args[1], "avalanche") == 0) {
5791 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]);
5792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005794 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005795 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005796 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
5799 }
Bhaskar98634f02013-10-29 23:30:51 -04005800
5801 /* set the hash function to use */
5802 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005803 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005804 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005805
5806 /* if consistent with no argument, then avalanche modifier is also applied */
5807 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5808 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005809 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005810 /* set the hash function */
5811 if (!strcmp(args[2], "sdbm")) {
5812 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5813 }
5814 else if (!strcmp(args[2], "djb2")) {
5815 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005816 }
5817 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005818 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005819 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005820 else if (!strcmp(args[2], "crc32")) {
5821 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5822 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005823 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005824 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 -05005825 err_code |= ERR_ALERT | ERR_FATAL;
5826 goto out;
5827 }
5828
5829 /* set the hash modifier */
5830 if (!strcmp(args[3], "avalanche")) {
5831 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5832 }
5833 else if (*args[3]) {
5834 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5835 err_code |= ERR_ALERT | ERR_FATAL;
5836 goto out;
5837 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005838 }
William Lallemanda73203e2012-03-12 12:48:57 +01005839 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005840 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5841 if (*(args[1]) == 0) {
5842 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
5845 }
5846 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5847 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5848 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5849 err_code |= ERR_ALERT | ERR_FATAL;
5850 goto out;
5851 }
5852 }
William Lallemanda73203e2012-03-12 12:48:57 +01005853 else if (strcmp(args[0], "unique-id-format") == 0) {
5854 if (!*(args[1])) {
5855 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5856 err_code |= ERR_ALERT | ERR_FATAL;
5857 goto out;
5858 }
William Lallemand3203ff42012-11-11 17:30:56 +01005859 if (*(args[2])) {
5860 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5861 err_code |= ERR_ALERT | ERR_FATAL;
5862 goto out;
5863 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005864 free(curproxy->conf.uniqueid_format_string);
5865 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005866
Willy Tarreau62a61232013-04-12 18:13:46 +02005867 free(curproxy->conf.uif_file);
5868 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5869 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005870 }
William Lallemanda73203e2012-03-12 12:48:57 +01005871
5872 else if (strcmp(args[0], "unique-id-header") == 0) {
5873 if (!*(args[1])) {
5874 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877 }
5878 free(curproxy->header_unique_id);
5879 curproxy->header_unique_id = strdup(args[1]);
5880 }
5881
William Lallemand723b73a2012-02-08 16:37:49 +01005882 else if (strcmp(args[0], "log-format") == 0) {
5883 if (!*(args[1])) {
5884 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
5887 }
William Lallemand3203ff42012-11-11 17:30:56 +01005888 if (*(args[2])) {
5889 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5890 err_code |= ERR_ALERT | ERR_FATAL;
5891 goto out;
5892 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005893 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5894 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005895
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005896 if (curproxy->conf.logformat_string == default_http_log_format)
5897 oldlogformat = "option httplog";
5898 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5899 oldlogformat = "option tcplog";
5900 else if (curproxy->conf.logformat_string == clf_http_log_format)
5901 oldlogformat = "option httplog clf";
5902 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5903 file, linenum, oldlogformat);
5904 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005905 if (curproxy->conf.logformat_string != default_http_log_format &&
5906 curproxy->conf.logformat_string != default_tcp_log_format &&
5907 curproxy->conf.logformat_string != clf_http_log_format)
5908 free(curproxy->conf.logformat_string);
5909 curproxy->conf.logformat_string = strdup(args[1]);
5910
5911 free(curproxy->conf.lfs_file);
5912 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5913 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005914
5915 /* get a chance to improve log-format error reporting by
5916 * reporting the correct line-number when possible.
5917 */
5918 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5919 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5920 file, linenum, curproxy->id);
5921 err_code |= ERR_WARN;
5922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005924 else if (!strcmp(args[0], "log-format-sd")) {
5925 if (!*(args[1])) {
5926 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5927 err_code |= ERR_ALERT | ERR_FATAL;
5928 goto out;
5929 }
5930 if (*(args[2])) {
5931 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5932 err_code |= ERR_ALERT | ERR_FATAL;
5933 goto out;
5934 }
5935
5936 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5937 free(curproxy->conf.logformat_sd_string);
5938 curproxy->conf.logformat_sd_string = strdup(args[1]);
5939
5940 free(curproxy->conf.lfsd_file);
5941 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5942 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5943
5944 /* get a chance to improve log-format-sd error reporting by
5945 * reporting the correct line-number when possible.
5946 */
5947 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5948 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5949 file, linenum, curproxy->id);
5950 err_code |= ERR_WARN;
5951 }
5952 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005953 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5954 if (*(args[1]) == 0) {
5955 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5956 err_code |= ERR_ALERT | ERR_FATAL;
5957 goto out;
5958 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005959 chunk_destroy(&curproxy->log_tag);
5960 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005961 }
William Lallemand0f99e342011-10-12 17:50:54 +02005962 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5963 /* delete previous herited or defined syslog servers */
5964 struct logsrv *back;
5965
5966 if (*(args[1]) != 0) {
5967 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5968 err_code |= ERR_ALERT | ERR_FATAL;
5969 goto out;
5970 }
5971
William Lallemand723b73a2012-02-08 16:37:49 +01005972 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5973 LIST_DEL(&tmplogsrv->list);
5974 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005975 }
5976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005978 struct logsrv *logsrv;
5979
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005981 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005982 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005983 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005984 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005985 LIST_INIT(&node->list);
5986 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 }
5989 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005990 struct sockaddr_storage *sk;
5991 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005992 int arg = 0;
5993 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005994
Vincent Bernat02779b62016-04-03 13:48:43 +02005995 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996
Willy Tarreau18324f52014-06-27 18:10:07 +02005997 /* just after the address, a length may be specified */
5998 if (strcmp(args[arg+2], "len") == 0) {
5999 len = atoi(args[arg+3]);
6000 if (len < 80 || len > 65535) {
6001 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6002 file, linenum, args[arg+3]);
6003 err_code |= ERR_ALERT | ERR_FATAL;
6004 goto out;
6005 }
6006 logsrv->maxlen = len;
6007
6008 /* skip these two args */
6009 arg += 2;
6010 }
6011 else
6012 logsrv->maxlen = MAX_SYSLOG_LEN;
6013
6014 if (logsrv->maxlen > global.max_syslog_len) {
6015 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006016 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6017 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6018 logline = my_realloc2(logline, global.max_syslog_len + 1);
6019 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006020 }
6021
Dragan Dosen1322d092015-09-22 16:05:32 +02006022 /* after the length, a format may be specified */
6023 if (strcmp(args[arg+2], "format") == 0) {
6024 logsrv->format = get_log_format(args[arg+3]);
6025 if (logsrv->format < 0) {
6026 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
6029 }
6030
6031 /* skip these two args */
6032 arg += 2;
6033 }
6034
William Lallemanddf1425a2015-04-28 20:17:49 +02006035 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6036 goto out;
6037
Willy Tarreau18324f52014-06-27 18:10:07 +02006038 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006039 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006040 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006041 err_code |= ERR_ALERT | ERR_FATAL;
6042 goto out;
6043
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044 }
6045
William Lallemand0f99e342011-10-12 17:50:54 +02006046 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006047 if (*(args[arg+3])) {
6048 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006049 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006050 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006051 err_code |= ERR_ALERT | ERR_FATAL;
6052 goto out;
6053
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054 }
6055 }
6056
William Lallemand0f99e342011-10-12 17:50:54 +02006057 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006058 if (*(args[arg+4])) {
6059 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006060 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006061 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006062 err_code |= ERR_ALERT | ERR_FATAL;
6063 goto out;
6064
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006065 }
6066 }
6067
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006068 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006069 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006070 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006071 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006072 goto out;
6073 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006074
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006075 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006076
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006077 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006078 if (port1 != port2) {
6079 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6080 file, linenum, args[0], args[1]);
6081 err_code |= ERR_ALERT | ERR_FATAL;
6082 goto out;
6083 }
6084
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006085 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006086 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006087 }
William Lallemand0f99e342011-10-12 17:50:54 +02006088
6089 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006090 }
6091 else {
6092 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6093 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006094 err_code |= ERR_ALERT | ERR_FATAL;
6095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006096 }
6097 }
6098 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006099 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006100 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006101 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006102 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006103
Willy Tarreau977b8e42006-12-29 14:19:17 +01006104 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006105 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006106
Willy Tarreaubaaee002006-06-26 02:48:02 +02006107 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006108 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6109 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006113
6114 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006115 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6116 free(curproxy->conn_src.iface_name);
6117 curproxy->conn_src.iface_name = NULL;
6118 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006119
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006120 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006121 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006122 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006123 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006125 goto out;
6126 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006127
6128 proto = protocol_by_family(sk->ss_family);
6129 if (!proto || !proto->connect) {
6130 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006131 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006132 err_code |= ERR_ALERT | ERR_FATAL;
6133 goto out;
6134 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006135
6136 if (port1 != port2) {
6137 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6138 file, linenum, args[0], args[1]);
6139 err_code |= ERR_ALERT | ERR_FATAL;
6140 goto out;
6141 }
6142
Willy Tarreauef9a3602012-12-08 22:29:20 +01006143 curproxy->conn_src.source_addr = *sk;
6144 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006145
6146 cur_arg = 2;
6147 while (*(args[cur_arg])) {
6148 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006149#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006150 if (!*args[cur_arg + 1]) {
6151 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6152 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006155 }
6156
6157 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006158 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6159 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006160 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006161 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6162 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006163 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6164 char *name, *end;
6165
6166 name = args[cur_arg+1] + 7;
6167 while (isspace(*name))
6168 name++;
6169
6170 end = name;
6171 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6172 end++;
6173
Willy Tarreauef9a3602012-12-08 22:29:20 +01006174 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6175 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6176 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6177 curproxy->conn_src.bind_hdr_len = end - name;
6178 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6179 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6180 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006181
6182 /* now look for an occurrence number */
6183 while (isspace(*end))
6184 end++;
6185 if (*end == ',') {
6186 end++;
6187 name = end;
6188 if (*end == '-')
6189 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006190 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006191 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006192 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006193 }
6194
Willy Tarreauef9a3602012-12-08 22:29:20 +01006195 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006196 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6197 " occurrences values smaller than %d.\n",
6198 file, linenum, MAX_HDR_HISTORY);
6199 err_code |= ERR_ALERT | ERR_FATAL;
6200 goto out;
6201 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006202 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006203 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006204
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006205 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006206 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006207 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006208 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006209 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006210 goto out;
6211 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006212
6213 proto = protocol_by_family(sk->ss_family);
6214 if (!proto || !proto->connect) {
6215 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6216 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006217 err_code |= ERR_ALERT | ERR_FATAL;
6218 goto out;
6219 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006220
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006221 if (port1 != port2) {
6222 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6223 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
6226 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006227 curproxy->conn_src.tproxy_addr = *sk;
6228 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006229 }
6230 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006231#else /* no TPROXY support */
6232 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006233 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006234 err_code |= ERR_ALERT | ERR_FATAL;
6235 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006236#endif
6237 cur_arg += 2;
6238 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006239 }
6240
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006241 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6242#ifdef SO_BINDTODEVICE
6243 if (!*args[cur_arg + 1]) {
6244 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006246 err_code |= ERR_ALERT | ERR_FATAL;
6247 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006248 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006249 free(curproxy->conn_src.iface_name);
6250 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6251 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006252 global.last_checks |= LSTCHK_NETADM;
6253#else
6254 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6255 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006256 err_code |= ERR_ALERT | ERR_FATAL;
6257 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006258#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006259 cur_arg += 2;
6260 continue;
6261 }
6262 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006263 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006268 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6269 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6270 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006274 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006275 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006276 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6277 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006281
6282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006283 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006284 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 }
6288 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006290 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006291 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006294 }
6295 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006296 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006297 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006298 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006299 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 }
6302 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006304 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006305 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 }
6309 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006310 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006311 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006312 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006313 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006316 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006317 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006318 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006319 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006320 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006321 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006324 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006325 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6326 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006327 err_code |= ERR_ALERT | ERR_FATAL;
6328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006330
6331 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006332 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006333 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006334 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 }
6337 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006338 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006339 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006340 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006341 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 }
6344 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006346 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006347 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006348 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
6351 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006353 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006354 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 }
6358 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006360 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006365 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006367 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006370 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006373 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006374
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 if (curproxy == &defproxy) {
6376 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006377 err_code |= ERR_ALERT | ERR_FATAL;
6378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006380 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006381 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006382
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 if (*(args[1]) == 0) {
6384 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006385 err_code |= ERR_ALERT | ERR_FATAL;
6386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006388
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006389 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006390 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6391 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6392 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006393 err_code |= ERR_ALERT | ERR_FATAL;
6394 goto out;
6395 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006396 err_code |= warnif_cond_conflicts(cond,
6397 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6398 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006399 }
6400 else if (*args[2]) {
6401 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6402 file, linenum, args[0], args[2]);
6403 err_code |= ERR_ALERT | ERR_FATAL;
6404 goto out;
6405 }
6406
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006407 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006408 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006409 wl->s = strdup(args[1]);
6410 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006411 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
6413 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6416 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006417 err_code |= ERR_ALERT | ERR_FATAL;
6418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006420
Willy Tarreauade5ec42010-01-28 19:33:49 +01006421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006422 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006423 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
6427 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006429 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006430 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 }
6434 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006436 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 }
6441 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006442 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006445 err_code |= ERR_ALERT | ERR_FATAL;
6446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 }
6448
Willy Tarreauade5ec42010-01-28 19:33:49 +01006449 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006450 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006451 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006452 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 }
6455 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006456 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006457 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006458 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006459 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461 }
6462 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006463 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006464 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006465 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006466 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006468 }
6469 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006470 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006471
Willy Tarreaubaaee002006-06-26 02:48:02 +02006472 if (curproxy == &defproxy) {
6473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006474 err_code |= ERR_ALERT | ERR_FATAL;
6475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006477 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006478 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006479
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 if (*(args[1]) == 0) {
6481 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006482 err_code |= ERR_ALERT | ERR_FATAL;
6483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 }
6485
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006486 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006487 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6488 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6489 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006490 err_code |= ERR_ALERT | ERR_FATAL;
6491 goto out;
6492 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006493 err_code |= warnif_cond_conflicts(cond,
6494 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6495 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006496 }
6497 else if (*args[2]) {
6498 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6499 file, linenum, args[0], args[2]);
6500 err_code |= ERR_ALERT | ERR_FATAL;
6501 goto out;
6502 }
6503
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006504 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006505 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006506 wl->s = strdup(args[1]);
6507 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 }
6509 else if (!strcmp(args[0], "errorloc") ||
6510 !strcmp(args[0], "errorloc302") ||
6511 !strcmp(args[0], "errorloc303")) { /* error location */
6512 int errnum, errlen;
6513 char *err;
6514
Willy Tarreau977b8e42006-12-29 14:19:17 +01006515 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006516 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006517
Willy Tarreaubaaee002006-06-26 02:48:02 +02006518 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006519 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006520 err_code |= ERR_ALERT | ERR_FATAL;
6521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522 }
6523
6524 errnum = atol(args[1]);
6525 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006526 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6527 err = malloc(errlen);
6528 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006530 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6531 err = malloc(errlen);
6532 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533 }
6534
Willy Tarreau0f772532006-12-23 20:51:41 +01006535 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6536 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006537 chunk_destroy(&curproxy->errmsg[rc]);
6538 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006539 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006542
6543 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006544 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6545 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006546 free(err);
6547 }
6548 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006549 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6550 int errnum, errlen, fd;
6551 char *err;
6552 struct stat stat;
6553
6554 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006555 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006556
6557 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006558 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006559 err_code |= ERR_ALERT | ERR_FATAL;
6560 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006561 }
6562
6563 fd = open(args[2], O_RDONLY);
6564 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6565 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6566 file, linenum, args[2], args[1]);
6567 if (fd >= 0)
6568 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006569 err_code |= ERR_ALERT | ERR_FATAL;
6570 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006571 }
6572
Willy Tarreau27a674e2009-08-17 07:23:33 +02006573 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006574 errlen = stat.st_size;
6575 } else {
6576 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006577 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006578 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006579 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006580 }
6581
6582 err = malloc(errlen); /* malloc() must succeed during parsing */
6583 errnum = read(fd, err, errlen);
6584 if (errnum != errlen) {
6585 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6586 file, linenum, args[2], args[1]);
6587 close(fd);
6588 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006589 err_code |= ERR_ALERT | ERR_FATAL;
6590 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006591 }
6592 close(fd);
6593
6594 errnum = atol(args[1]);
6595 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6596 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006597 chunk_destroy(&curproxy->errmsg[rc]);
6598 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006599 break;
6600 }
6601 }
6602
6603 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006604 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6605 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006606 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006607 free(err);
6608 }
6609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006611 struct cfg_kw_list *kwl;
6612 int index;
6613
6614 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6615 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6616 if (kwl->kw[index].section != CFG_LISTEN)
6617 continue;
6618 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6619 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006620 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006621 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006622 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006623 err_code |= ERR_ALERT | ERR_FATAL;
6624 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006625 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006626 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006627 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006628 err_code |= ERR_WARN;
6629 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006630 }
Willy Tarreau93893792009-07-23 13:19:11 +02006631 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006632 }
6633 }
6634 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006635
Willy Tarreau6daf3432008-01-22 16:44:08 +01006636 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006637 err_code |= ERR_ALERT | ERR_FATAL;
6638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006639 }
Willy Tarreau93893792009-07-23 13:19:11 +02006640 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006641 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006642 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006643}
6644
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006645int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006646cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6647{
6648#ifdef CONFIG_HAP_NS
6649 const char *err;
6650 const char *item = args[0];
6651
6652 if (!strcmp(item, "namespace_list")) {
6653 return 0;
6654 }
6655 else if (!strcmp(item, "namespace")) {
6656 size_t idx = 1;
6657 const char *current;
6658 while (*(current = args[idx++])) {
6659 err = invalid_char(current);
6660 if (err) {
6661 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6662 file, linenum, *err, item, current);
6663 return ERR_ALERT | ERR_FATAL;
6664 }
6665
6666 if (netns_store_lookup(current, strlen(current))) {
6667 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6668 file, linenum, current);
6669 return ERR_ALERT | ERR_FATAL;
6670 }
6671 if (!netns_store_insert(current)) {
6672 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6673 file, linenum, current);
6674 return ERR_ALERT | ERR_FATAL;
6675 }
6676 }
6677 }
6678
6679 return 0;
6680#else
6681 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6682 file, linenum);
6683 return ERR_ALERT | ERR_FATAL;
6684#endif
6685}
6686
6687int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006688cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6689{
6690
6691 int err_code = 0;
6692 const char *err;
6693
6694 if (!strcmp(args[0], "userlist")) { /* new userlist */
6695 struct userlist *newul;
6696
6697 if (!*args[1]) {
6698 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6699 file, linenum, args[0]);
6700 err_code |= ERR_ALERT | ERR_FATAL;
6701 goto out;
6702 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6704 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006705
6706 err = invalid_char(args[1]);
6707 if (err) {
6708 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6709 file, linenum, *err, args[0], args[1]);
6710 err_code |= ERR_ALERT | ERR_FATAL;
6711 goto out;
6712 }
6713
6714 for (newul = userlist; newul; newul = newul->next)
6715 if (!strcmp(newul->name, args[1])) {
6716 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6717 file, linenum, args[1]);
6718 err_code |= ERR_WARN;
6719 goto out;
6720 }
6721
Vincent Bernat02779b62016-04-03 13:48:43 +02006722 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006723 if (!newul) {
6724 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6725 err_code |= ERR_ALERT | ERR_ABORT;
6726 goto out;
6727 }
6728
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006729 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006730 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006731 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6732 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006733 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006734 goto out;
6735 }
6736
6737 newul->next = userlist;
6738 userlist = newul;
6739
6740 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006741 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006743 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006744
6745 if (!*args[1]) {
6746 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6747 file, linenum, args[0]);
6748 err_code |= ERR_ALERT | ERR_FATAL;
6749 goto out;
6750 }
6751
6752 err = invalid_char(args[1]);
6753 if (err) {
6754 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6755 file, linenum, *err, args[0], args[1]);
6756 err_code |= ERR_ALERT | ERR_FATAL;
6757 goto out;
6758 }
6759
William Lallemand4ac9f542015-05-28 18:03:51 +02006760 if (!userlist)
6761 goto out;
6762
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006763 for (ag = userlist->groups; ag; ag = ag->next)
6764 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006765 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6766 file, linenum, args[1], userlist->name);
6767 err_code |= ERR_ALERT;
6768 goto out;
6769 }
6770
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006771 ag = calloc(1, sizeof(*ag));
6772 if (!ag) {
6773 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6774 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006775 goto out;
6776 }
6777
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006778 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006779 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006780 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6781 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006782 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006783 goto out;
6784 }
6785
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006786 cur_arg = 2;
6787
6788 while (*args[cur_arg]) {
6789 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006790 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006791 cur_arg += 2;
6792 continue;
6793 } else {
6794 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6795 file, linenum, args[0]);
6796 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006797 free(ag->groupusers);
6798 free(ag->name);
6799 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 goto out;
6801 }
6802 }
6803
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006804 ag->next = userlist->groups;
6805 userlist->groups = ag;
6806
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006807 } else if (!strcmp(args[0], "user")) { /* new user */
6808 struct auth_users *newuser;
6809 int cur_arg;
6810
6811 if (!*args[1]) {
6812 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6813 file, linenum, args[0]);
6814 err_code |= ERR_ALERT | ERR_FATAL;
6815 goto out;
6816 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006817 if (!userlist)
6818 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006819
6820 for (newuser = userlist->users; newuser; newuser = newuser->next)
6821 if (!strcmp(newuser->user, args[1])) {
6822 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6823 file, linenum, args[1], userlist->name);
6824 err_code |= ERR_ALERT;
6825 goto out;
6826 }
6827
Vincent Bernat02779b62016-04-03 13:48:43 +02006828 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006829 if (!newuser) {
6830 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6831 err_code |= ERR_ALERT | ERR_ABORT;
6832 goto out;
6833 }
6834
6835 newuser->user = strdup(args[1]);
6836
6837 newuser->next = userlist->users;
6838 userlist->users = newuser;
6839
6840 cur_arg = 2;
6841
6842 while (*args[cur_arg]) {
6843 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006844#ifdef CONFIG_HAP_CRYPT
6845 if (!crypt("", args[cur_arg + 1])) {
6846 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6847 file, linenum, newuser->user);
6848 err_code |= ERR_ALERT | ERR_FATAL;
6849 goto out;
6850 }
6851#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006852 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6853 file, linenum);
6854 err_code |= ERR_ALERT;
6855#endif
6856 newuser->pass = strdup(args[cur_arg + 1]);
6857 cur_arg += 2;
6858 continue;
6859 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6860 newuser->pass = strdup(args[cur_arg + 1]);
6861 newuser->flags |= AU_O_INSECURE;
6862 cur_arg += 2;
6863 continue;
6864 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006865 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006866 cur_arg += 2;
6867 continue;
6868 } else {
6869 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6870 file, linenum, args[0]);
6871 err_code |= ERR_ALERT | ERR_FATAL;
6872 goto out;
6873 }
6874 }
6875 } else {
6876 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6877 err_code |= ERR_ALERT | ERR_FATAL;
6878 }
6879
6880out:
6881 return err_code;
6882}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006883
Christopher Faulet79bdef32016-11-04 22:36:15 +01006884int
6885cfg_parse_scope(const char *file, int linenum, char *line)
6886{
6887 char *beg, *end, *scope = NULL;
6888 int err_code = 0;
6889 const char *err;
6890
6891 beg = line + 1;
6892 end = strchr(beg, ']');
6893
6894 /* Detect end of scope declaration */
6895 if (!end || end == beg) {
6896 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6897 file, linenum);
6898 err_code |= ERR_ALERT | ERR_FATAL;
6899 goto out;
6900 }
6901
6902 /* Get scope name and check its validity */
6903 scope = my_strndup(beg, end-beg);
6904 err = invalid_char(scope);
6905 if (err) {
6906 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6907 file, linenum, *err);
6908 err_code |= ERR_ALERT | ERR_ABORT;
6909 goto out;
6910 }
6911
6912 /* Be sure to have a scope declaration alone on its line */
6913 line = end+1;
6914 while (isspace((unsigned char)*line))
6915 line++;
6916 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6917 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6918 file, linenum, *line);
6919 err_code |= ERR_ALERT | ERR_ABORT;
6920 goto out;
6921 }
6922
6923 /* We have a valid scope declaration, save it */
6924 free(cfg_scope);
6925 cfg_scope = scope;
6926 scope = NULL;
6927
6928 out:
6929 free(scope);
6930 return err_code;
6931}
6932
Willy Tarreaubaaee002006-06-26 02:48:02 +02006933/*
6934 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006935 * Returns the error code, 0 if OK, or any combination of :
6936 * - ERR_ABORT: must abort ASAP
6937 * - ERR_FATAL: we can continue parsing but not start the service
6938 * - ERR_WARN: a warning has been emitted
6939 * - ERR_ALERT: an alert has been emitted
6940 * Only the two first ones can stop processing, the two others are just
6941 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006942 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006943int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944{
William Lallemand64e84512015-05-12 14:25:37 +02006945 char *thisline;
6946 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006947 FILE *f;
6948 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006949 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006950 struct cfg_section *cs = NULL;
6951 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006952 int readbytes = 0;
6953
6954 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006955 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006956 return -1;
6957 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006958
David Carlier97880bb2016-04-08 10:35:26 +01006959 if ((f=fopen(file,"r")) == NULL) {
6960 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006961 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006963
William Lallemandb2f07452015-05-12 14:27:13 +02006964next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006965 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006966 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006967 char *end;
6968 char *args[MAX_LINE_ARGS + 1];
6969 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006970 int dquote = 0; /* double quote */
6971 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006972
Willy Tarreaubaaee002006-06-26 02:48:02 +02006973 linenum++;
6974
6975 end = line + strlen(line);
6976
William Lallemand64e84512015-05-12 14:25:37 +02006977 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006978 /* Check if we reached the limit and the last char is not \n.
6979 * Watch out for the last line without the terminating '\n'!
6980 */
William Lallemand64e84512015-05-12 14:25:37 +02006981 char *newline;
6982 int newlinesize = linesize * 2;
6983
6984 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6985 if (newline == NULL) {
6986 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6987 file, linenum);
6988 err_code |= ERR_ALERT | ERR_FATAL;
6989 continue;
6990 }
6991
6992 readbytes = linesize - 1;
6993 linesize = newlinesize;
6994 thisline = newline;
6995 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006996 }
6997
William Lallemand64e84512015-05-12 14:25:37 +02006998 readbytes = 0;
6999
Willy Tarreaubaaee002006-06-26 02:48:02 +02007000 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007001 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007002 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007003
Christopher Faulet79bdef32016-11-04 22:36:15 +01007004
7005 if (*line == '[') {/* This is the begining if a scope */
7006 err_code |= cfg_parse_scope(file, linenum, line);
7007 goto next_line;
7008 }
7009
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010 arg = 0;
7011 args[arg] = line;
7012
7013 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007014 if (*line == '"' && !squote) { /* double quote outside single quotes */
7015 if (dquote)
7016 dquote = 0;
7017 else
7018 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007019 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007020 end--;
7021 }
7022 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7023 if (squote)
7024 squote = 0;
7025 else
7026 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007027 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007028 end--;
7029 }
7030 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007031 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7032 * C equivalent value. Other combinations left unchanged (eg: \1).
7033 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034 int skip = 0;
7035 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7036 *line = line[1];
7037 skip = 1;
7038 }
7039 else if (line[1] == 'r') {
7040 *line = '\r';
7041 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007043 else if (line[1] == 'n') {
7044 *line = '\n';
7045 skip = 1;
7046 }
7047 else if (line[1] == 't') {
7048 *line = '\t';
7049 skip = 1;
7050 }
7051 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007052 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007053 unsigned char hex1, hex2;
7054 hex1 = toupper(line[2]) - '0';
7055 hex2 = toupper(line[3]) - '0';
7056 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7057 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7058 *line = (hex1<<4) + hex2;
7059 skip = 3;
7060 }
7061 else {
7062 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007063 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007064 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007065 } else if (line[1] == '"') {
7066 *line = '"';
7067 skip = 1;
7068 } else if (line[1] == '\'') {
7069 *line = '\'';
7070 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007071 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7072 *line = '$';
7073 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007074 }
7075 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007076 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007077 end -= skip;
7078 }
7079 line++;
7080 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007081 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007082 /* end of string, end of loop */
7083 *line = 0;
7084 break;
7085 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007086 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007087 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007088 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007089 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007090 line++;
7091 args[++arg] = line;
7092 }
William Lallemandb2f07452015-05-12 14:27:13 +02007093 else if (dquote && *line == '$') {
7094 /* environment variables are evaluated inside double quotes */
7095 char *var_beg;
7096 char *var_end;
7097 char save_char;
7098 char *value;
7099 int val_len;
7100 int newlinesize;
7101 int braces = 0;
7102
7103 var_beg = line + 1;
7104 var_end = var_beg;
7105
7106 if (*var_beg == '{') {
7107 var_beg++;
7108 var_end++;
7109 braces = 1;
7110 }
7111
7112 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7113 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7114 err_code |= ERR_ALERT | ERR_FATAL;
7115 goto next_line; /* skip current line */
7116 }
7117
7118 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7119 var_end++;
7120
7121 save_char = *var_end;
7122 *var_end = '\0';
7123 value = getenv(var_beg);
7124 *var_end = save_char;
7125 val_len = value ? strlen(value) : 0;
7126
7127 if (braces) {
7128 if (*var_end == '}') {
7129 var_end++;
7130 braces = 0;
7131 } else {
7132 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7133 err_code |= ERR_ALERT | ERR_FATAL;
7134 goto next_line; /* skip current line */
7135 }
7136 }
7137
7138 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7139
7140 /* if not enough space in thisline */
7141 if (newlinesize > linesize) {
7142 char *newline;
7143
7144 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7145 if (newline == NULL) {
7146 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7147 err_code |= ERR_ALERT | ERR_FATAL;
7148 goto next_line; /* slip current line */
7149 }
7150 /* recompute pointers if realloc returns a new pointer */
7151 if (newline != thisline) {
7152 int i;
7153 int diff;
7154
7155 for (i = 0; i <= arg; i++) {
7156 diff = args[i] - thisline;
7157 args[i] = newline + diff;
7158 }
7159
7160 diff = var_end - thisline;
7161 var_end = newline + diff;
7162 diff = end - thisline;
7163 end = newline + diff;
7164 diff = line - thisline;
7165 line = newline + diff;
7166 thisline = newline;
7167 }
7168 linesize = newlinesize;
7169 }
7170
7171 /* insert value inside the line */
7172 memmove(line + val_len, var_end, end - var_end + 1);
7173 memcpy(line, value, val_len);
7174 end += val_len - (var_end - line);
7175 line += val_len;
7176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007177 else {
7178 line++;
7179 }
7180 }
William Lallemandb2f07452015-05-12 14:27:13 +02007181
William Lallemandf9873ba2015-05-05 17:37:14 +02007182 if (dquote) {
7183 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7184 err_code |= ERR_ALERT | ERR_FATAL;
7185 }
7186
7187 if (squote) {
7188 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7189 err_code |= ERR_ALERT | ERR_FATAL;
7190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007191
7192 /* empty line */
7193 if (!**args)
7194 continue;
7195
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007196 if (*line) {
7197 /* we had to stop due to too many args.
7198 * Let's terminate the string, print the offending part then cut the
7199 * last arg.
7200 */
7201 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7202 line++;
7203 *line = '\0';
7204
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007205 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007206 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007207 err_code |= ERR_ALERT | ERR_FATAL;
7208 args[arg] = line;
7209 }
7210
Willy Tarreau540abe42007-05-02 20:50:16 +02007211 /* zero out remaining args and ensure that at least one entry
7212 * is zeroed out.
7213 */
7214 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007215 args[arg] = line;
7216 }
7217
Willy Tarreau3842f002009-06-14 11:39:52 +02007218 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007219 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007220 char *tmp;
7221
Willy Tarreau3842f002009-06-14 11:39:52 +02007222 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007223 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007224 for (arg=0; *args[arg+1]; arg++)
7225 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007226 *tmp = '\0'; // fix the next arg to \0
7227 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007228 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007229 else if (!strcmp(args[0], "default")) {
7230 kwm = KWM_DEF;
7231 for (arg=0; *args[arg+1]; arg++)
7232 args[arg] = args[arg+1]; // shift args after inversion
7233 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007234
William Lallemand0f99e342011-10-12 17:50:54 +02007235 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7236 strcmp(args[0], "log") != 0) {
7237 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007238 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007239 }
7240
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007241 /* detect section start */
7242 list_for_each_entry(ics, &sections, list) {
7243 if (strcmp(args[0], ics->section_name) == 0) {
7244 cursection = ics->section_name;
7245 cs = ics;
7246 break;
7247 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007248 }
7249
Willy Tarreaubaaee002006-06-26 02:48:02 +02007250 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007251 if (cs)
7252 err_code |= cs->section_parser(file, linenum, args, kwm);
7253 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007254 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007255 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007256 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007257
7258 if (err_code & ERR_ABORT)
7259 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007260 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007261 free(cfg_scope);
7262 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007263 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007264 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007265 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007266 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007267}
7268
Willy Tarreau64ab6072014-09-16 12:17:36 +02007269/* This function propagates processes from frontend <from> to backend <to> so
7270 * that it is always guaranteed that a backend pointed to by a frontend is
7271 * bound to all of its processes. After that, if the target is a "listen"
7272 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007273 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007274 * checked first to ensure that <to> is already bound to all processes of
7275 * <from>, there is no risk of looping and we ensure to follow the shortest
7276 * path to the destination.
7277 *
7278 * It is possible to set <to> to NULL for the first call so that the function
7279 * takes care of visiting the initial frontend in <from>.
7280 *
7281 * It is important to note that the function relies on the fact that all names
7282 * have already been resolved.
7283 */
7284void propagate_processes(struct proxy *from, struct proxy *to)
7285{
7286 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007287
7288 if (to) {
7289 /* check whether we need to go down */
7290 if (from->bind_proc &&
7291 (from->bind_proc & to->bind_proc) == from->bind_proc)
7292 return;
7293
7294 if (!from->bind_proc && !to->bind_proc)
7295 return;
7296
7297 to->bind_proc = from->bind_proc ?
7298 (to->bind_proc | from->bind_proc) : 0;
7299
7300 /* now propagate down */
7301 from = to;
7302 }
7303
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007304 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007305 return;
7306
Willy Tarreauf6b70012014-12-18 14:00:43 +01007307 if (from->state == PR_STSTOPPED)
7308 return;
7309
Willy Tarreau64ab6072014-09-16 12:17:36 +02007310 /* default_backend */
7311 if (from->defbe.be)
7312 propagate_processes(from, from->defbe.be);
7313
7314 /* use_backend */
7315 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007316 if (rule->dynamic)
7317 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007318 to = rule->be.backend;
7319 propagate_processes(from, to);
7320 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007321}
7322
Willy Tarreaubb925012009-07-23 13:36:36 +02007323/*
7324 * Returns the error code, 0 if OK, or any combination of :
7325 * - ERR_ABORT: must abort ASAP
7326 * - ERR_FATAL: we can continue parsing but not start the service
7327 * - ERR_WARN: a warning has been emitted
7328 * - ERR_ALERT: an alert has been emitted
7329 * Only the two first ones can stop processing, the two others are just
7330 * indicators.
7331 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007332int check_config_validity()
7333{
7334 int cfgerr = 0;
7335 struct proxy *curproxy = NULL;
7336 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007337 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007338 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007339 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007340 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007341
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007342 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007343 /*
7344 * Now, check for the integrity of all that we have collected.
7345 */
7346
7347 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007348 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007349
Willy Tarreau193b8c62012-11-22 00:17:38 +01007350 if (!global.tune.max_http_hdr)
7351 global.tune.max_http_hdr = MAX_HTTP_HDR;
7352
7353 if (!global.tune.cookie_len)
7354 global.tune.cookie_len = CAPTURE_LEN;
7355
7356 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7357
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007358 /* Post initialisation of the users and groups lists. */
7359 err_code = userlist_postinit();
7360 if (err_code != ERR_NONE)
7361 goto out;
7362
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007363 /* first, we will invert the proxy list order */
7364 curproxy = NULL;
7365 while (proxy) {
7366 struct proxy *next;
7367
7368 next = proxy->next;
7369 proxy->next = curproxy;
7370 curproxy = proxy;
7371 if (!next)
7372 break;
7373 proxy = next;
7374 }
7375
Willy Tarreau419ead82014-09-16 13:41:21 +02007376 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007377 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007378 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007379 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007380 struct act_rule *trule;
7381 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007382 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007383 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007384 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007385
Willy Tarreau050536d2012-10-04 08:47:34 +02007386 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007387 /* proxy ID not set, use automatic numbering with first
7388 * spare entry starting with next_pxid.
7389 */
7390 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7391 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7392 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007393 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007394 next_pxid++;
7395
Willy Tarreau55ea7572007-06-17 19:56:27 +02007396
Willy Tarreaubaaee002006-06-26 02:48:02 +02007397 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007398 /* ensure we don't keep listeners uselessly bound */
7399 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007400 free((void *)curproxy->table.peers.name);
7401 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007402 continue;
7403 }
7404
Willy Tarreau102df612014-05-07 23:56:38 +02007405 /* Check multi-process mode compatibility for the current proxy */
7406
7407 if (curproxy->bind_proc) {
7408 /* an explicit bind-process was specified, let's check how many
7409 * processes remain.
7410 */
David Carliere6c39412015-07-02 07:00:17 +00007411 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007412
7413 curproxy->bind_proc &= nbits(global.nbproc);
7414 if (!curproxy->bind_proc && nbproc == 1) {
7415 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);
7416 curproxy->bind_proc = 1;
7417 }
7418 else if (!curproxy->bind_proc && nbproc > 1) {
7419 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);
7420 curproxy->bind_proc = 0;
7421 }
7422 }
7423
Willy Tarreau3d209582014-05-09 17:06:11 +02007424 /* check and reduce the bind-proc of each listener */
7425 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7426 unsigned long mask;
7427
7428 if (!bind_conf->bind_proc)
7429 continue;
7430
7431 mask = nbits(global.nbproc);
7432 if (curproxy->bind_proc)
7433 mask &= curproxy->bind_proc;
7434 /* mask cannot be null here thanks to the previous checks */
7435
David Carliere6c39412015-07-02 07:00:17 +00007436 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007437 bind_conf->bind_proc &= mask;
7438
7439 if (!bind_conf->bind_proc && nbproc == 1) {
7440 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",
7441 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7442 bind_conf->bind_proc = mask & ~(mask - 1);
7443 }
7444 else if (!bind_conf->bind_proc && nbproc > 1) {
7445 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",
7446 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7447 bind_conf->bind_proc = 0;
7448 }
7449 }
7450
Willy Tarreauff01a212009-03-15 13:46:16 +01007451 switch (curproxy->mode) {
7452 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007453 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007454 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007455 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7456 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007457 cfgerr++;
7458 }
7459
7460 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007461 Warning("config : servers will be ignored for %s '%s'.\n",
7462 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007463 break;
7464
7465 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007466 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007467 break;
7468
7469 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007470 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007471 break;
7472 }
7473
Willy Tarreauf3934b82015-08-11 11:36:45 +02007474 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7475 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7476 proxy_type_str(curproxy), curproxy->id);
7477 err_code |= ERR_WARN;
7478 }
7479
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007480 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007481 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007482 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007483 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7484 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007485 cfgerr++;
7486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007487#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007488 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007489 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7490 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007491 cfgerr++;
7492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007493#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007494 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007495 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7496 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007497 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007498 }
7499 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007500 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007501 /* If no LB algo is set in a backend, and we're not in
7502 * transparent mode, dispatch mode nor proxy mode, we
7503 * want to use balance roundrobin by default.
7504 */
7505 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7506 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007507 }
7508 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007509
Willy Tarreau1620ec32011-08-06 17:05:02 +02007510 if (curproxy->options & PR_O_DISPATCH)
7511 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7512 else if (curproxy->options & PR_O_HTTP_PROXY)
7513 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7514 else if (curproxy->options & PR_O_TRANSP)
7515 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007516
Willy Tarreau1620ec32011-08-06 17:05:02 +02007517 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7518 if (curproxy->options & PR_O_DISABLE404) {
7519 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7520 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7521 err_code |= ERR_WARN;
7522 curproxy->options &= ~PR_O_DISABLE404;
7523 }
7524 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7525 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7526 "send-state", proxy_type_str(curproxy), curproxy->id);
7527 err_code |= ERR_WARN;
7528 curproxy->options &= ~PR_O2_CHK_SNDST;
7529 }
Willy Tarreauef781042010-01-27 11:53:01 +01007530 }
7531
Simon Horman98637e52014-06-20 12:30:16 +09007532 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7533 if (!global.external_check) {
7534 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7535 curproxy->id, "option external-check");
7536 cfgerr++;
7537 }
7538 if (!curproxy->check_command) {
7539 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7540 curproxy->id, "option external-check");
7541 cfgerr++;
7542 }
7543 }
7544
Simon Horman64e34162015-02-06 11:11:57 +09007545 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007546 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7547 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007548 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7549 "'email-alert myhostname', or 'email-alert to' "
7550 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007551 "to be present).\n",
7552 proxy_type_str(curproxy), curproxy->id);
7553 err_code |= ERR_WARN;
7554 free_email_alert(curproxy);
7555 }
7556 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007557 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007558 }
7559
Simon Horman98637e52014-06-20 12:30:16 +09007560 if (curproxy->check_command) {
7561 int clear = 0;
7562 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7563 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7564 "external-check command", proxy_type_str(curproxy), curproxy->id);
7565 err_code |= ERR_WARN;
7566 clear = 1;
7567 }
7568 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007569 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007570 curproxy->id, "external-check command");
7571 cfgerr++;
7572 }
7573 if (clear) {
7574 free(curproxy->check_command);
7575 curproxy->check_command = NULL;
7576 }
7577 }
7578
7579 if (curproxy->check_path) {
7580 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7581 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7582 "external-check path", proxy_type_str(curproxy), curproxy->id);
7583 err_code |= ERR_WARN;
7584 free(curproxy->check_path);
7585 curproxy->check_path = NULL;
7586 }
7587 }
7588
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007589 /* if a default backend was specified, let's find it */
7590 if (curproxy->defbe.name) {
7591 struct proxy *target;
7592
Willy Tarreauafb39922015-05-26 12:04:09 +02007593 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007594 if (!target) {
7595 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7596 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007597 cfgerr++;
7598 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007599 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7600 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007601 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007602 } else if (target->mode != curproxy->mode &&
7603 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7604
7605 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7606 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7607 curproxy->conf.file, curproxy->conf.line,
7608 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7609 target->conf.file, target->conf.line);
7610 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007611 } else {
7612 free(curproxy->defbe.name);
7613 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007614 /* Update tot_fe_maxconn for a further fullconn's computation */
7615 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007616 /* Emit a warning if this proxy also has some servers */
7617 if (curproxy->srv) {
7618 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7619 curproxy->id);
7620 err_code |= ERR_WARN;
7621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007622 }
7623 }
7624
Emeric Brun3f783572017-01-12 11:21:28 +01007625 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7626 /* Case of listen without default backend
7627 * The curproxy will be its own default backend
7628 * so we update tot_fe_maxconn for a further
7629 * fullconn's computation */
7630 curproxy->tot_fe_maxconn += curproxy->maxconn;
7631 }
7632
Willy Tarreau55ea7572007-06-17 19:56:27 +02007633 /* find the target proxy for 'use_backend' rules */
7634 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007635 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007636 struct logformat_node *node;
7637 char *pxname;
7638
7639 /* Try to parse the string as a log format expression. If the result
7640 * of the parsing is only one entry containing a simple string, then
7641 * it's a standard string corresponding to a static rule, thus the
7642 * parsing is cancelled and be.name is restored to be resolved.
7643 */
7644 pxname = rule->be.name;
7645 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007646 curproxy->conf.args.ctx = ARGC_UBK;
7647 curproxy->conf.args.file = rule->file;
7648 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007649 err = NULL;
7650 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7651 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7652 rule->file, rule->line, pxname, err);
7653 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007654 cfgerr++;
7655 continue;
7656 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007657 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7658
7659 if (!LIST_ISEMPTY(&rule->be.expr)) {
7660 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7661 rule->dynamic = 1;
7662 free(pxname);
7663 continue;
7664 }
7665 /* simple string: free the expression and fall back to static rule */
7666 free(node->arg);
7667 free(node);
7668 }
7669
7670 rule->dynamic = 0;
7671 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007672
Willy Tarreauafb39922015-05-26 12:04:09 +02007673 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007674 if (!target) {
7675 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7676 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007677 cfgerr++;
7678 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007679 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7680 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007681 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007682 } else if (target->mode != curproxy->mode &&
7683 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7684
7685 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7686 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7687 curproxy->conf.file, curproxy->conf.line,
7688 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7689 target->conf.file, target->conf.line);
7690 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007691 } else {
7692 free((void *)rule->be.name);
7693 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007694 /* For each target of switching rules, we update
7695 * their tot_fe_maxconn, except if a previous rule point
7696 * on the same backend or on the default backend */
7697 if (rule->be.backend != curproxy->defbe.be) {
7698 struct switching_rule *swrule;
7699
7700 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7701 if (rule == swrule) {
7702 target->tot_fe_maxconn += curproxy->maxconn;
7703 break;
7704 }
7705 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7706 /* there is multiple ref of this backend */
7707 break;
7708 }
7709 }
7710 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007711 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007712 }
7713
Willy Tarreau64ab6072014-09-16 12:17:36 +02007714 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007715 list_for_each_entry(srule, &curproxy->server_rules, list) {
7716 struct server *target = findserver(curproxy, srule->srv.name);
7717
7718 if (!target) {
7719 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7720 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7721 cfgerr++;
7722 continue;
7723 }
7724 free((void *)srule->srv.name);
7725 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007726 }
7727
Emeric Brunb982a3d2010-01-04 15:45:53 +01007728 /* find the target table for 'stick' rules */
7729 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7730 struct proxy *target;
7731
Emeric Brun1d33b292010-01-04 15:47:17 +01007732 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7733 if (mrule->flags & STK_IS_STORE)
7734 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7735
Emeric Brunb982a3d2010-01-04 15:45:53 +01007736 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007737 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007738 else
7739 target = curproxy;
7740
7741 if (!target) {
7742 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7743 curproxy->id, mrule->table.name);
7744 cfgerr++;
7745 }
7746 else if (target->table.size == 0) {
7747 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7748 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7749 cfgerr++;
7750 }
Willy Tarreau12785782012-04-27 21:37:17 +02007751 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7752 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007753 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7754 cfgerr++;
7755 }
7756 else {
7757 free((void *)mrule->table.name);
7758 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007759 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007760 }
7761 }
7762
7763 /* find the target table for 'store response' rules */
7764 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7765 struct proxy *target;
7766
Emeric Brun1d33b292010-01-04 15:47:17 +01007767 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7768
Emeric Brunb982a3d2010-01-04 15:45:53 +01007769 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007770 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007771 else
7772 target = curproxy;
7773
7774 if (!target) {
7775 Alert("Proxy '%s': unable to find store table '%s'.\n",
7776 curproxy->id, mrule->table.name);
7777 cfgerr++;
7778 }
7779 else if (target->table.size == 0) {
7780 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7781 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7782 cfgerr++;
7783 }
Willy Tarreau12785782012-04-27 21:37:17 +02007784 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7785 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007786 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7787 cfgerr++;
7788 }
7789 else {
7790 free((void *)mrule->table.name);
7791 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007792 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007793 }
7794 }
7795
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007796 /* find the target table for 'tcp-request' layer 4 rules */
7797 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7798 struct proxy *target;
7799
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007800 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007801 continue;
7802
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007803 if (trule->arg.trk_ctr.table.n)
7804 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007805 else
7806 target = curproxy;
7807
7808 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007809 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007810 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007811 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007812 cfgerr++;
7813 }
7814 else if (target->table.size == 0) {
7815 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007816 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007817 cfgerr++;
7818 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007819 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007820 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007821 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007822 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007823 cfgerr++;
7824 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007825 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007826 free(trule->arg.trk_ctr.table.n);
7827 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007828 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007829 * to pass a list of counters to track and allocate them right here using
7830 * stktable_alloc_data_type().
7831 */
7832 }
7833 }
7834
Willy Tarreau620408f2016-10-21 16:37:51 +02007835 /* find the target table for 'tcp-request' layer 5 rules */
7836 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7837 struct proxy *target;
7838
7839 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7840 continue;
7841
7842 if (trule->arg.trk_ctr.table.n)
7843 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7844 else
7845 target = curproxy;
7846
7847 if (!target) {
7848 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7849 curproxy->id, trule->arg.trk_ctr.table.n,
7850 tcp_trk_idx(trule->action));
7851 cfgerr++;
7852 }
7853 else if (target->table.size == 0) {
7854 Alert("Proxy '%s': table '%s' used but not configured.\n",
7855 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7856 cfgerr++;
7857 }
7858 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7859 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7860 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7861 tcp_trk_idx(trule->action));
7862 cfgerr++;
7863 }
7864 else {
7865 free(trule->arg.trk_ctr.table.n);
7866 trule->arg.trk_ctr.table.t = &target->table;
7867 /* Note: if we decide to enhance the track-sc syntax, we may be able
7868 * to pass a list of counters to track and allocate them right here using
7869 * stktable_alloc_data_type().
7870 */
7871 }
7872 }
7873
Willy Tarreaud1f96522010-08-03 19:34:32 +02007874 /* find the target table for 'tcp-request' layer 6 rules */
7875 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7876 struct proxy *target;
7877
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007878 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007879 continue;
7880
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007881 if (trule->arg.trk_ctr.table.n)
7882 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007883 else
7884 target = curproxy;
7885
7886 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007887 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007888 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007889 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007890 cfgerr++;
7891 }
7892 else if (target->table.size == 0) {
7893 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007894 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007895 cfgerr++;
7896 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007897 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007898 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007899 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007900 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007901 cfgerr++;
7902 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007903 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007904 free(trule->arg.trk_ctr.table.n);
7905 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007906 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007907 * to pass a list of counters to track and allocate them right here using
7908 * stktable_alloc_data_type().
7909 */
7910 }
7911 }
7912
Baptiste Assmanne9544932015-11-03 23:31:35 +01007913 /* parse http-request capture rules to ensure id really exists */
7914 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7915 if (hrqrule->action != ACT_CUSTOM ||
7916 hrqrule->action_ptr != http_action_req_capture_by_id)
7917 continue;
7918
7919 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7920 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7921 curproxy->id, hrqrule->arg.capid.idx);
7922 cfgerr++;
7923 }
7924 }
7925
7926 /* parse http-response capture rules to ensure id really exists */
7927 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7928 if (hrqrule->action != ACT_CUSTOM ||
7929 hrqrule->action_ptr != http_action_res_capture_by_id)
7930 continue;
7931
7932 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7933 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7934 curproxy->id, hrqrule->arg.capid.idx);
7935 cfgerr++;
7936 }
7937 }
7938
Willy Tarreau09448f72014-06-25 18:12:15 +02007939 /* find the target table for 'http-request' layer 7 rules */
7940 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7941 struct proxy *target;
7942
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007943 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007944 continue;
7945
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007946 if (hrqrule->arg.trk_ctr.table.n)
7947 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007948 else
7949 target = curproxy;
7950
7951 if (!target) {
7952 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007953 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007954 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007955 cfgerr++;
7956 }
7957 else if (target->table.size == 0) {
7958 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007959 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007960 cfgerr++;
7961 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007962 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007963 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007964 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007965 http_trk_idx(hrqrule->action));
7966 cfgerr++;
7967 }
7968 else {
7969 free(hrqrule->arg.trk_ctr.table.n);
7970 hrqrule->arg.trk_ctr.table.t = &target->table;
7971 /* Note: if we decide to enhance the track-sc syntax, we may be able
7972 * to pass a list of counters to track and allocate them right here using
7973 * stktable_alloc_data_type().
7974 */
7975 }
7976 }
7977
7978 /* find the target table for 'http-response' layer 7 rules */
7979 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7980 struct proxy *target;
7981
7982 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7983 continue;
7984
7985 if (hrqrule->arg.trk_ctr.table.n)
7986 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7987 else
7988 target = curproxy;
7989
7990 if (!target) {
7991 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7992 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7993 http_trk_idx(hrqrule->action));
7994 cfgerr++;
7995 }
7996 else if (target->table.size == 0) {
7997 Alert("Proxy '%s': table '%s' used but not configured.\n",
7998 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
7999 cfgerr++;
8000 }
8001 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8002 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8003 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8004 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008005 cfgerr++;
8006 }
8007 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008008 free(hrqrule->arg.trk_ctr.table.n);
8009 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008010 /* Note: if we decide to enhance the track-sc syntax, we may be able
8011 * to pass a list of counters to track and allocate them right here using
8012 * stktable_alloc_data_type().
8013 */
8014 }
8015 }
8016
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008017 /* move any "block" rules at the beginning of the http-request rules */
8018 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8019 /* insert block_rules into http_req_rules at the beginning */
8020 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8021 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8022 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8023 curproxy->http_req_rules.n = curproxy->block_rules.n;
8024 LIST_INIT(&curproxy->block_rules);
8025 }
8026
Emeric Brun32da3c42010-09-23 18:39:19 +02008027 if (curproxy->table.peers.name) {
8028 struct peers *curpeers = peers;
8029
8030 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8031 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8032 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008033 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008034 break;
8035 }
8036 }
8037
8038 if (!curpeers) {
8039 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8040 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008041 free((void *)curproxy->table.peers.name);
8042 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008043 cfgerr++;
8044 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008045 else if (curpeers->state == PR_STSTOPPED) {
8046 /* silently disable this peers section */
8047 curproxy->table.peers.p = NULL;
8048 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008049 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008050 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8051 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008052 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008053 cfgerr++;
8054 }
8055 }
8056
Simon Horman9dc49962015-01-30 11:22:59 +09008057
8058 if (curproxy->email_alert.mailers.name) {
8059 struct mailers *curmailers = mailers;
8060
8061 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8062 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8063 free(curproxy->email_alert.mailers.name);
8064 curproxy->email_alert.mailers.m = curmailers;
8065 curmailers->users++;
8066 break;
8067 }
8068 }
8069
8070 if (!curmailers) {
8071 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8072 curproxy->id, curproxy->email_alert.mailers.name);
8073 free_email_alert(curproxy);
8074 cfgerr++;
8075 }
8076 }
8077
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008078 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008079 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008080 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8081 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8082 "proxy", curproxy->id);
8083 cfgerr++;
8084 goto out_uri_auth_compat;
8085 }
8086
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008087 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008088 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008089 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008090 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008091
Willy Tarreau95fa4692010-02-01 13:05:50 +01008092 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8093 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008094
8095 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008096 uri_auth_compat_req[i++] = "realm";
8097 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8098 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008099
Willy Tarreau95fa4692010-02-01 13:05:50 +01008100 uri_auth_compat_req[i++] = "unless";
8101 uri_auth_compat_req[i++] = "{";
8102 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8103 uri_auth_compat_req[i++] = "}";
8104 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008105
Willy Tarreauff011f22011-01-06 17:51:27 +01008106 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8107 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008108 cfgerr++;
8109 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008110 }
8111
Willy Tarreauff011f22011-01-06 17:51:27 +01008112 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008113
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008114 if (curproxy->uri_auth->auth_realm) {
8115 free(curproxy->uri_auth->auth_realm);
8116 curproxy->uri_auth->auth_realm = NULL;
8117 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008118
8119 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008120 }
8121out_uri_auth_compat:
8122
Dragan Dosen43885c72015-10-01 13:18:13 +02008123 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008124 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008125 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8126 if (!curproxy->conf.logformat_sd_string) {
8127 /* set the default logformat_sd_string */
8128 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8129 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008130 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008131 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008132 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008133
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008134 /* compile the log format */
8135 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008136 if (curproxy->conf.logformat_string != default_http_log_format &&
8137 curproxy->conf.logformat_string != default_tcp_log_format &&
8138 curproxy->conf.logformat_string != clf_http_log_format)
8139 free(curproxy->conf.logformat_string);
8140 curproxy->conf.logformat_string = NULL;
8141 free(curproxy->conf.lfs_file);
8142 curproxy->conf.lfs_file = NULL;
8143 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008144
8145 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8146 free(curproxy->conf.logformat_sd_string);
8147 curproxy->conf.logformat_sd_string = NULL;
8148 free(curproxy->conf.lfsd_file);
8149 curproxy->conf.lfsd_file = NULL;
8150 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008151 }
8152
Willy Tarreau62a61232013-04-12 18:13:46 +02008153 if (curproxy->conf.logformat_string) {
8154 curproxy->conf.args.ctx = ARGC_LOG;
8155 curproxy->conf.args.file = curproxy->conf.lfs_file;
8156 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008157 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008158 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008159 SMP_VAL_FE_LOG_END, &err)) {
8160 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8161 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8162 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008163 cfgerr++;
8164 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008165 curproxy->conf.args.file = NULL;
8166 curproxy->conf.args.line = 0;
8167 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008168
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008169 if (curproxy->conf.logformat_sd_string) {
8170 curproxy->conf.args.ctx = ARGC_LOGSD;
8171 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8172 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008173 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008174 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 +01008175 SMP_VAL_FE_LOG_END, &err)) {
8176 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8177 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8178 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008179 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008180 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8181 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8182 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8183 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008184 cfgerr++;
8185 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008186 curproxy->conf.args.file = NULL;
8187 curproxy->conf.args.line = 0;
8188 }
8189
Willy Tarreau62a61232013-04-12 18:13:46 +02008190 if (curproxy->conf.uniqueid_format_string) {
8191 curproxy->conf.args.ctx = ARGC_UIF;
8192 curproxy->conf.args.file = curproxy->conf.uif_file;
8193 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008194 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008195 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 +01008196 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8197 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8198 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8199 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008200 cfgerr++;
8201 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008202 curproxy->conf.args.file = NULL;
8203 curproxy->conf.args.line = 0;
8204 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008205
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008206 /* only now we can check if some args remain unresolved.
8207 * This must be done after the users and groups resolution.
8208 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008209 cfgerr += smp_resolve_args(curproxy);
8210 if (!cfgerr)
8211 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008212
Willy Tarreau2738a142006-07-08 17:28:09 +02008213 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008214 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008215 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008216 (!curproxy->timeout.connect ||
8217 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008218 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008219 " | While not properly invalid, you will certainly encounter various problems\n"
8220 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008221 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008222 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008223 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008224 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008225
Willy Tarreau1fa31262007-12-03 00:36:16 +01008226 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8227 * We must still support older configurations, so let's find out whether those
8228 * parameters have been set or must be copied from contimeouts.
8229 */
8230 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008231 if (!curproxy->timeout.tarpit ||
8232 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008233 /* tarpit timeout not set. We search in the following order:
8234 * default.tarpit, curr.connect, default.connect.
8235 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008236 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008237 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008238 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008239 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008240 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008241 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008242 }
8243 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008244 (!curproxy->timeout.queue ||
8245 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008246 /* queue timeout not set. We search in the following order:
8247 * default.queue, curr.connect, default.connect.
8248 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008249 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008250 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008251 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008252 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008253 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008254 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008255 }
8256 }
8257
Willy Tarreau1620ec32011-08-06 17:05:02 +02008258 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008259 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008260 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008261 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008262 }
8263
Willy Tarreau215663d2014-06-13 18:30:23 +02008264 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8265 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8266 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8267 proxy_type_str(curproxy), curproxy->id);
8268 err_code |= ERR_WARN;
8269 }
8270
Willy Tarreau193b8c62012-11-22 00:17:38 +01008271 /* ensure that cookie capture length is not too large */
8272 if (curproxy->capture_len >= global.tune.cookie_len) {
8273 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8274 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8275 err_code |= ERR_WARN;
8276 curproxy->capture_len = global.tune.cookie_len - 1;
8277 }
8278
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008279 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008280 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008281 curproxy->req_cap_pool = create_pool("ptrcap",
8282 curproxy->nb_req_cap * sizeof(char *),
8283 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008284 }
8285
8286 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008287 curproxy->rsp_cap_pool = create_pool("ptrcap",
8288 curproxy->nb_rsp_cap * sizeof(char *),
8289 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008290 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008291
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008292 switch (curproxy->load_server_state_from_file) {
8293 case PR_SRV_STATE_FILE_UNSPEC:
8294 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8295 break;
8296 case PR_SRV_STATE_FILE_GLOBAL:
8297 if (!global.server_state_file) {
8298 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",
8299 curproxy->id);
8300 err_code |= ERR_WARN;
8301 }
8302 break;
8303 }
8304
Willy Tarreaubaaee002006-06-26 02:48:02 +02008305 /* first, we will invert the servers list order */
8306 newsrv = NULL;
8307 while (curproxy->srv) {
8308 struct server *next;
8309
8310 next = curproxy->srv->next;
8311 curproxy->srv->next = newsrv;
8312 newsrv = curproxy->srv;
8313 if (!next)
8314 break;
8315 curproxy->srv = next;
8316 }
8317
Willy Tarreau17edc812014-01-03 12:14:34 +01008318 /* Check that no server name conflicts. This causes trouble in the stats.
8319 * We only emit a warning for the first conflict affecting each server,
8320 * in order to avoid combinatory explosion if all servers have the same
8321 * name. We do that only for servers which do not have an explicit ID,
8322 * because these IDs were made also for distinguishing them and we don't
8323 * want to annoy people who correctly manage them.
8324 */
8325 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8326 struct server *other_srv;
8327
8328 if (newsrv->puid)
8329 continue;
8330
8331 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8332 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8333 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8334 newsrv->conf.file, newsrv->conf.line,
8335 proxy_type_str(curproxy), curproxy->id,
8336 newsrv->id, other_srv->conf.line);
8337 break;
8338 }
8339 }
8340 }
8341
Willy Tarreaudd701652010-05-25 23:03:02 +02008342 /* assign automatic UIDs to servers which don't have one yet */
8343 next_id = 1;
8344 newsrv = curproxy->srv;
8345 while (newsrv != NULL) {
8346 if (!newsrv->puid) {
8347 /* server ID not set, use automatic numbering with first
8348 * spare entry starting with next_svid.
8349 */
8350 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8351 newsrv->conf.id.key = newsrv->puid = next_id;
8352 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8353 }
8354 next_id++;
8355 newsrv = newsrv->next;
8356 }
8357
Willy Tarreau20697042007-11-15 23:26:18 +01008358 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008359 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008360
Willy Tarreau62c3be22012-01-20 13:12:32 +01008361 /*
8362 * If this server supports a maxconn parameter, it needs a dedicated
8363 * tasks to fill the emptied slots when a connection leaves.
8364 * Also, resolve deferred tracking dependency if needed.
8365 */
8366 newsrv = curproxy->srv;
8367 while (newsrv != NULL) {
8368 if (newsrv->minconn > newsrv->maxconn) {
8369 /* Only 'minconn' was specified, or it was higher than or equal
8370 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8371 * this will avoid further useless expensive computations.
8372 */
8373 newsrv->maxconn = newsrv->minconn;
8374 } else if (newsrv->maxconn && !newsrv->minconn) {
8375 /* minconn was not specified, so we set it to maxconn */
8376 newsrv->minconn = newsrv->maxconn;
8377 }
8378
Willy Tarreau17d45382016-12-22 21:16:08 +01008379 /* this will also properly set the transport layer for prod and checks */
8380 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8381 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8382 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8383 }
Emeric Brun94324a42012-10-11 14:00:19 +02008384
Willy Tarreau2f075e92013-12-03 11:11:34 +01008385 /* set the check type on the server */
8386 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8387
Willy Tarreau62c3be22012-01-20 13:12:32 +01008388 if (newsrv->trackit) {
8389 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008390 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008391 char *pname, *sname;
8392
8393 pname = newsrv->trackit;
8394 sname = strrchr(pname, '/');
8395
8396 if (sname)
8397 *sname++ = '\0';
8398 else {
8399 sname = pname;
8400 pname = NULL;
8401 }
8402
8403 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008404 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008405 if (!px) {
8406 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8407 proxy_type_str(curproxy), curproxy->id,
8408 newsrv->id, pname);
8409 cfgerr++;
8410 goto next_srv;
8411 }
8412 } else
8413 px = curproxy;
8414
8415 srv = findserver(px, sname);
8416 if (!srv) {
8417 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8418 proxy_type_str(curproxy), curproxy->id,
8419 newsrv->id, sname);
8420 cfgerr++;
8421 goto next_srv;
8422 }
8423
Willy Tarreau32091232014-05-16 13:52:00 +02008424 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8425 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8426 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008427 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008428 "tracking as it does not have any check nor agent enabled.\n",
8429 proxy_type_str(curproxy), curproxy->id,
8430 newsrv->id, px->id, srv->id);
8431 cfgerr++;
8432 goto next_srv;
8433 }
8434
8435 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8436
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008437 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008438 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8439 "belongs to a tracking chain looping back to %s/%s.\n",
8440 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008441 newsrv->id, px->id, srv->id, px->id,
8442 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008443 cfgerr++;
8444 goto next_srv;
8445 }
8446
8447 if (curproxy != px &&
8448 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8449 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8450 "tracking: disable-on-404 option inconsistency.\n",
8451 proxy_type_str(curproxy), curproxy->id,
8452 newsrv->id, px->id, srv->id);
8453 cfgerr++;
8454 goto next_srv;
8455 }
8456
Willy Tarreau62c3be22012-01-20 13:12:32 +01008457 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008458 newsrv->tracknext = srv->trackers;
8459 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008460
8461 free(newsrv->trackit);
8462 newsrv->trackit = NULL;
8463 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008464
8465 /*
8466 * resolve server's resolvers name and update the resolvers pointer
8467 * accordingly
8468 */
8469 if (newsrv->resolvers_id) {
8470 struct dns_resolvers *curr_resolvers;
8471 int found;
8472
8473 found = 0;
8474 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8475 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8476 found = 1;
8477 break;
8478 }
8479 }
8480
8481 if (!found) {
8482 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8483 proxy_type_str(curproxy), curproxy->id,
8484 newsrv->id, newsrv->resolvers_id);
8485 cfgerr++;
8486 } else {
8487 free(newsrv->resolvers_id);
8488 newsrv->resolvers_id = NULL;
8489 if (newsrv->resolution)
8490 newsrv->resolution->resolvers = curr_resolvers;
8491 }
8492 }
8493 else {
8494 /* if no resolvers section associated to this server
8495 * we can clean up the associated resolution structure
8496 */
8497 if (newsrv->resolution) {
8498 free(newsrv->resolution->hostname_dn);
8499 newsrv->resolution->hostname_dn = NULL;
8500 free(newsrv->resolution);
8501 newsrv->resolution = NULL;
8502 }
8503 }
8504
Willy Tarreau62c3be22012-01-20 13:12:32 +01008505 next_srv:
8506 newsrv = newsrv->next;
8507 }
8508
Olivier Houchard4e694042017-03-14 20:01:29 +01008509 /*
8510 * Try to generate dynamic cookies for servers now.
8511 * It couldn't be done earlier, since at the time we parsed
8512 * the server line, we may not have known yet that we
8513 * should use dynamic cookies, or the secret key may not
8514 * have been provided yet.
8515 */
8516 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8517 newsrv = curproxy->srv;
8518 while (newsrv != NULL) {
8519 srv_set_dyncookie(newsrv);
8520 newsrv = newsrv->next;
8521 }
8522
8523 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008524 /* We have to initialize the server lookup mechanism depending
8525 * on what LB algorithm was choosen.
8526 */
8527
8528 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8529 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8530 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008531 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8532 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8533 init_server_map(curproxy);
8534 } else {
8535 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8536 fwrr_init_server_groups(curproxy);
8537 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008538 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008539
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008540 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008541 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8542 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8543 fwlc_init_server_tree(curproxy);
8544 } else {
8545 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8546 fas_init_server_tree(curproxy);
8547 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008548 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008549
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008550 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008551 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8552 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8553 chash_init_server_tree(curproxy);
8554 } else {
8555 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8556 init_server_map(curproxy);
8557 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008558 break;
8559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008560
8561 if (curproxy->options & PR_O_LOGASAP)
8562 curproxy->to_log &= ~LW_BYTES;
8563
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008564 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008565 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8566 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008567 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8568 proxy_type_str(curproxy), curproxy->id);
8569 err_code |= ERR_WARN;
8570 }
8571
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008572 if (curproxy->mode != PR_MODE_HTTP) {
8573 int optnum;
8574
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008575 if (curproxy->uri_auth) {
8576 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8577 proxy_type_str(curproxy), curproxy->id);
8578 err_code |= ERR_WARN;
8579 curproxy->uri_auth = NULL;
8580 }
8581
Willy Tarreaude7dc882017-03-10 11:49:21 +01008582 if (curproxy->capture_name) {
8583 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8584 proxy_type_str(curproxy), curproxy->id);
8585 err_code |= ERR_WARN;
8586 }
8587
8588 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8589 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8590 proxy_type_str(curproxy), curproxy->id);
8591 err_code |= ERR_WARN;
8592 }
8593
8594 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8595 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8596 proxy_type_str(curproxy), curproxy->id);
8597 err_code |= ERR_WARN;
8598 }
8599
8600 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8601 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8602 proxy_type_str(curproxy), curproxy->id);
8603 err_code |= ERR_WARN;
8604 }
8605
8606 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8607 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8608 proxy_type_str(curproxy), curproxy->id);
8609 err_code |= ERR_WARN;
8610 }
8611
Willy Tarreau87cf5142011-08-19 22:57:24 +02008612 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008613 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8614 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8615 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008616 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008617 }
8618
8619 if (curproxy->options & PR_O_ORGTO) {
8620 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8621 "originalto", proxy_type_str(curproxy), curproxy->id);
8622 err_code |= ERR_WARN;
8623 curproxy->options &= ~PR_O_ORGTO;
8624 }
8625
8626 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8627 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8628 (curproxy->cap & cfg_opts[optnum].cap) &&
8629 (curproxy->options & cfg_opts[optnum].val)) {
8630 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8631 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8632 err_code |= ERR_WARN;
8633 curproxy->options &= ~cfg_opts[optnum].val;
8634 }
8635 }
8636
8637 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8638 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8639 (curproxy->cap & cfg_opts2[optnum].cap) &&
8640 (curproxy->options2 & cfg_opts2[optnum].val)) {
8641 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8642 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8643 err_code |= ERR_WARN;
8644 curproxy->options2 &= ~cfg_opts2[optnum].val;
8645 }
8646 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008647
Willy Tarreau29fbe512015-08-20 19:35:14 +02008648#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008649 if (curproxy->conn_src.bind_hdr_occ) {
8650 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008651 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008652 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008653 err_code |= ERR_WARN;
8654 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008655#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008656 }
8657
Willy Tarreaubaaee002006-06-26 02:48:02 +02008658 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008659 * ensure that we're not cross-dressing a TCP server into HTTP.
8660 */
8661 newsrv = curproxy->srv;
8662 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008663 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008664 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8665 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008666 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008667 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008668
Willy Tarreau0cec3312011-10-31 13:49:26 +01008669 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8670 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8671 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8672 err_code |= ERR_WARN;
8673 }
8674
Willy Tarreauc93cd162014-05-13 15:54:22 +02008675 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008676 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8677 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8678 err_code |= ERR_WARN;
8679 }
8680
Willy Tarreau29fbe512015-08-20 19:35:14 +02008681#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008682 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8683 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008684 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 +01008685 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008686 err_code |= ERR_WARN;
8687 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008688#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008689
8690 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8691 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8692 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8693 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8694 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8695 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",
8696 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8697 err_code |= ERR_WARN;
8698 }
8699
8700
8701 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8702 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",
8703 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8704 err_code |= ERR_WARN;
8705 }
8706 }
8707
Willy Tarreau21d2af32008-02-14 20:25:24 +01008708 newsrv = newsrv->next;
8709 }
8710
Willy Tarreaue42bd962014-09-16 16:21:19 +02008711 /* check if we have a frontend with "tcp-request content" looking at L7
8712 * with no inspect-delay
8713 */
8714 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8715 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008716 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008717 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008718 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008719 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008720 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008721 break;
8722 }
8723
8724 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8725 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8726 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8727 " This means that these rules will randomly find their contents. This can be fixed by"
8728 " setting the tcp-request inspect-delay.\n",
8729 proxy_type_str(curproxy), curproxy->id);
8730 err_code |= ERR_WARN;
8731 }
8732 }
8733
Christopher Fauletd7c91962015-04-30 11:48:27 +02008734 /* Check filter configuration, if any */
8735 cfgerr += flt_check(curproxy);
8736
Willy Tarreauc1a21672009-08-16 22:37:44 +02008737 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008738 if (!curproxy->accept)
8739 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008740
Willy Tarreauc1a21672009-08-16 22:37:44 +02008741 if (curproxy->tcp_req.inspect_delay ||
8742 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008743 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008744
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008745 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008746 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008747 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008748 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008749
8750 /* both TCP and HTTP must check switching rules */
8751 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008752
8753 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008754 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008755 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8756 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 +01008757 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008758 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8759 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008760 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008761 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008762 }
8763
8764 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008765 if (curproxy->tcp_req.inspect_delay ||
8766 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8767 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8768
Emeric Brun97679e72010-09-23 17:56:44 +02008769 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8770 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8771
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008772 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008773 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008774 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008775 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008776
8777 /* If the backend does requires RDP cookie persistence, we have to
8778 * enable the corresponding analyser.
8779 */
8780 if (curproxy->options2 & PR_O2_RDPC_PRST)
8781 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008782
8783 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008784 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008785 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8786 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 +01008787 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008788 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8789 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008790 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008791 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008792 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008793 }
8794
8795 /***********************************************************/
8796 /* At this point, target names have already been resolved. */
8797 /***********************************************************/
8798
8799 /* Check multi-process mode compatibility */
8800
8801 if (global.nbproc > 1 && global.stats_fe) {
8802 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8803 unsigned long mask;
8804
8805 mask = nbits(global.nbproc);
8806 if (global.stats_fe->bind_proc)
8807 mask &= global.stats_fe->bind_proc;
8808
8809 if (bind_conf->bind_proc)
8810 mask &= bind_conf->bind_proc;
8811
8812 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008813 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008814 break;
8815 }
8816 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8817 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");
8818 }
8819 }
8820
8821 /* Make each frontend inherit bind-process from its listeners when not specified. */
8822 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8823 if (curproxy->bind_proc)
8824 continue;
8825
8826 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8827 unsigned long mask;
8828
Willy Tarreaue428b082015-05-04 21:57:58 +02008829 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008830 curproxy->bind_proc |= mask;
8831 }
8832
8833 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008834 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008835 }
8836
8837 if (global.stats_fe) {
8838 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8839 unsigned long mask;
8840
Cyril Bonté06181952016-02-24 00:14:54 +01008841 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008842 global.stats_fe->bind_proc |= mask;
8843 }
8844 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008845 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008846 }
8847
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008848 /* propagate bindings from frontends to backends. Don't do it if there
8849 * are any fatal errors as we must not call it with unresolved proxies.
8850 */
8851 if (!cfgerr) {
8852 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8853 if (curproxy->cap & PR_CAP_FE)
8854 propagate_processes(curproxy, NULL);
8855 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008856 }
8857
8858 /* Bind each unbound backend to all processes when not specified. */
8859 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8860 if (curproxy->bind_proc)
8861 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008862 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008863 }
8864
8865 /*******************************************************/
8866 /* At this step, all proxies have a non-null bind_proc */
8867 /*******************************************************/
8868
8869 /* perform the final checks before creating tasks */
8870
8871 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8872 struct listener *listener;
8873 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008874
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008875 /* Configure SSL for each bind line.
8876 * Note: if configuration fails at some point, the ->ctx member
8877 * remains NULL so that listeners can later detach.
8878 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008879 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008880 if (bind_conf->xprt->prepare_bind_conf &&
8881 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008882 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008883 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008884
Willy Tarreaue6b98942007-10-29 01:09:36 +01008885 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008886 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008887 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008888 int nbproc;
8889
8890 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008891 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008892 nbits(global.nbproc));
8893
8894 if (!nbproc) /* no intersection between listener and frontend */
8895 nbproc = 1;
8896
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008897 if (!listener->luid) {
8898 /* listener ID not set, use automatic numbering with first
8899 * spare entry starting with next_luid.
8900 */
8901 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8902 listener->conf.id.key = listener->luid = next_id;
8903 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008904 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008905 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008906
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008907 /* enable separate counters */
8908 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008909 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008910 if (!listener->name)
8911 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008912 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008913
Willy Tarreaue6b98942007-10-29 01:09:36 +01008914 if (curproxy->options & PR_O_TCP_NOLING)
8915 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008916 if (!listener->maxconn)
8917 listener->maxconn = curproxy->maxconn;
8918 if (!listener->backlog)
8919 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008920 if (!listener->maxaccept)
8921 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8922
8923 /* we want to have an optimal behaviour on single process mode to
8924 * maximize the work at once, but in multi-process we want to keep
8925 * some fairness between processes, so we target half of the max
8926 * number of events to be balanced over all the processes the proxy
8927 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8928 * used to disable the limit.
8929 */
8930 if (listener->maxaccept > 0) {
8931 if (nbproc > 1)
8932 listener->maxaccept = (listener->maxaccept + 1) / 2;
8933 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8934 }
8935
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008936 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008937 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008938 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008939 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008940
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008941 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008942 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008943
Willy Tarreau620408f2016-10-21 16:37:51 +02008944 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8945 listener->options |= LI_O_TCP_L5_RULES;
8946
Willy Tarreaude3041d2010-05-31 10:56:17 +02008947 if (curproxy->mon_mask.s_addr)
8948 listener->options |= LI_O_CHK_MONNET;
8949
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008950 /* smart accept mode is automatic in HTTP mode */
8951 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008952 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008953 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8954 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008955 }
8956
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008957 /* Release unused SSL configs */
8958 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008959 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8960 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008961 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008962
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008963 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008964 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008965 int count, maxproc = 0;
8966
8967 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008968 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008969 if (count > maxproc)
8970 maxproc = count;
8971 }
8972 /* backends have 0, frontends have 1 or more */
8973 if (maxproc != 1)
8974 Warning("Proxy '%s': in multi-process mode, stats will be"
8975 " limited to process assigned to the current request.\n",
8976 curproxy->id);
8977
Willy Tarreau102df612014-05-07 23:56:38 +02008978 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8979 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8980 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008981 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008982 }
Willy Tarreau102df612014-05-07 23:56:38 +02008983 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8984 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8985 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008986 }
8987 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008988
8989 /* create the task associated with the proxy */
8990 curproxy->task = task_new();
8991 if (curproxy->task) {
8992 curproxy->task->context = curproxy;
8993 curproxy->task->process = manage_proxy;
8994 /* no need to queue, it will be done automatically if some
8995 * listener gets limited.
8996 */
8997 curproxy->task->expire = TICK_ETERNITY;
8998 } else {
8999 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9000 curproxy->id);
9001 cfgerr++;
9002 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009003 }
9004
Willy Tarreaufbb78422011-06-05 15:38:35 +02009005 /* automatically compute fullconn if not set. We must not do it in the
9006 * loop above because cross-references are not yet fully resolved.
9007 */
9008 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9009 /* If <fullconn> is not set, let's set it to 10% of the sum of
9010 * the possible incoming frontend's maxconns.
9011 */
9012 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009013 /* we have the sum of the maxconns in <total>. We only
9014 * keep 10% of that sum to set the default fullconn, with
9015 * a hard minimum of 1 (to avoid a divide by zero).
9016 */
Emeric Brun3f783572017-01-12 11:21:28 +01009017 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009018 if (!curproxy->fullconn)
9019 curproxy->fullconn = 1;
9020 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009021 }
9022
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009023 /*
9024 * Recount currently required checks.
9025 */
9026
9027 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9028 int optnum;
9029
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009030 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9031 if (curproxy->options & cfg_opts[optnum].val)
9032 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009033
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009034 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9035 if (curproxy->options2 & cfg_opts2[optnum].val)
9036 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009037 }
9038
Willy Tarreau0fca4832015-05-01 19:12:05 +02009039 /* compute the required process bindings for the peers */
9040 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9041 if (curproxy->table.peers.p)
9042 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9043
Willy Tarreau122541c2011-09-07 21:24:49 +02009044 if (peers) {
9045 struct peers *curpeers = peers, **last;
9046 struct peer *p, *pb;
9047
Willy Tarreau1e273012015-05-01 19:15:17 +02009048 /* Remove all peers sections which don't have a valid listener,
9049 * which are not used by any table, or which are bound to more
9050 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009051 */
9052 last = &peers;
9053 while (*last) {
9054 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009055
9056 if (curpeers->state == PR_STSTOPPED) {
9057 /* the "disabled" keyword was present */
9058 if (curpeers->peers_fe)
9059 stop_proxy(curpeers->peers_fe);
9060 curpeers->peers_fe = NULL;
9061 }
9062 else if (!curpeers->peers_fe) {
9063 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9064 curpeers->id, localpeer);
9065 }
David Carliere6c39412015-07-02 07:00:17 +00009066 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009067 /* either it's totally stopped or too much used */
9068 if (curpeers->peers_fe->bind_proc) {
9069 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009070 "running in different processes (%d different ones). "
9071 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009072 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009073 cfgerr++;
9074 }
9075 stop_proxy(curpeers->peers_fe);
9076 curpeers->peers_fe = NULL;
9077 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009078 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009079 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009080 last = &curpeers->next;
9081 continue;
9082 }
9083
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009084 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009085 p = curpeers->remote;
9086 while (p) {
9087 pb = p->next;
9088 free(p->id);
9089 free(p);
9090 p = pb;
9091 }
9092
9093 /* Destroy and unlink this curpeers section.
9094 * Note: curpeers is backed up into *last.
9095 */
9096 free(curpeers->id);
9097 curpeers = curpeers->next;
9098 free(*last);
9099 *last = curpeers;
9100 }
9101 }
9102
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009103 /* initialize stick-tables on backend capable proxies. This must not
9104 * be done earlier because the data size may be discovered while parsing
9105 * other proxies.
9106 */
9107 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9108 if (curproxy->state == PR_STSTOPPED)
9109 continue;
9110
9111 if (!stktable_init(&curproxy->table)) {
9112 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9113 cfgerr++;
9114 }
9115 }
9116
Simon Horman0d16a402015-01-30 11:22:58 +09009117 if (mailers) {
9118 struct mailers *curmailers = mailers, **last;
9119 struct mailer *m, *mb;
9120
9121 /* Remove all mailers sections which don't have a valid listener.
9122 * This can happen when a mailers section is never referenced.
9123 */
9124 last = &mailers;
9125 while (*last) {
9126 curmailers = *last;
9127 if (curmailers->users) {
9128 last = &curmailers->next;
9129 continue;
9130 }
9131
9132 Warning("Removing incomplete section 'mailers %s'.\n",
9133 curmailers->id);
9134
9135 m = curmailers->mailer_list;
9136 while (m) {
9137 mb = m->next;
9138 free(m->id);
9139 free(m);
9140 m = mb;
9141 }
9142
9143 /* Destroy and unlink this curmailers section.
9144 * Note: curmailers is backed up into *last.
9145 */
9146 free(curmailers->id);
9147 curmailers = curmailers->next;
9148 free(*last);
9149 *last = curmailers;
9150 }
9151 }
9152
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009153 /* Update server_state_file_name to backend name if backend is supposed to use
9154 * a server-state file locally defined and none has been provided */
9155 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9156 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9157 curproxy->server_state_file_name == NULL)
9158 curproxy->server_state_file_name = strdup(curproxy->id);
9159 }
9160
Willy Tarreau34eb6712011-10-24 18:15:04 +02009161 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009162 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009163 MEM_F_SHARED);
9164
Willy Tarreaubb925012009-07-23 13:36:36 +02009165 if (cfgerr > 0)
9166 err_code |= ERR_ALERT | ERR_FATAL;
9167 out:
9168 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009169}
9170
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009171/*
9172 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9173 * parsing sessions.
9174 */
9175void cfg_register_keywords(struct cfg_kw_list *kwl)
9176{
9177 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9178}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009179
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009180/*
9181 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9182 */
9183void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9184{
9185 LIST_DEL(&kwl->list);
9186 LIST_INIT(&kwl->list);
9187}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009188
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009189/* this function register new section in the haproxy configuration file.
9190 * <section_name> is the name of this new section and <section_parser>
9191 * is the called parser. If two section declaration have the same name,
9192 * only the first declared is used.
9193 */
9194int cfg_register_section(char *section_name,
9195 int (*section_parser)(const char *, int, char **, int))
9196{
9197 struct cfg_section *cs;
9198
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009199 list_for_each_entry(cs, &sections, list) {
9200 if (strcmp(cs->section_name, section_name) == 0) {
9201 Alert("register section '%s': already registered.\n", section_name);
9202 return 0;
9203 }
9204 }
9205
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009206 cs = calloc(1, sizeof(*cs));
9207 if (!cs) {
9208 Alert("register section '%s': out of memory.\n", section_name);
9209 return 0;
9210 }
9211
9212 cs->section_name = section_name;
9213 cs->section_parser = section_parser;
9214
9215 LIST_ADDQ(&sections, &cs->list);
9216
9217 return 1;
9218}
9219
Willy Tarreaubaaee002006-06-26 02:48:02 +02009220/*
David Carlier845efb52015-09-25 11:49:18 +01009221 * free all config section entries
9222 */
9223void cfg_unregister_sections(void)
9224{
9225 struct cfg_section *cs, *ics;
9226
9227 list_for_each_entry_safe(cs, ics, &sections, list) {
9228 LIST_DEL(&cs->list);
9229 free(cs);
9230 }
9231}
9232
Christopher Faulet7110b402016-10-26 11:09:44 +02009233void cfg_backup_sections(struct list *backup_sections)
9234{
9235 struct cfg_section *cs, *ics;
9236
9237 list_for_each_entry_safe(cs, ics, &sections, list) {
9238 LIST_DEL(&cs->list);
9239 LIST_ADDQ(backup_sections, &cs->list);
9240 }
9241}
9242
9243void cfg_restore_sections(struct list *backup_sections)
9244{
9245 struct cfg_section *cs, *ics;
9246
9247 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9248 LIST_DEL(&cs->list);
9249 LIST_ADDQ(&sections, &cs->list);
9250 }
9251}
9252
Willy Tarreau659fbf02016-05-26 17:55:28 +02009253__attribute__((constructor))
9254static void cfgparse_init(void)
9255{
9256 /* Register internal sections */
9257 cfg_register_section("listen", cfg_parse_listen);
9258 cfg_register_section("frontend", cfg_parse_listen);
9259 cfg_register_section("backend", cfg_parse_listen);
9260 cfg_register_section("defaults", cfg_parse_listen);
9261 cfg_register_section("global", cfg_parse_global);
9262 cfg_register_section("userlist", cfg_parse_users);
9263 cfg_register_section("peers", cfg_parse_peers);
9264 cfg_register_section("mailers", cfg_parse_mailers);
9265 cfg_register_section("namespace_list", cfg_parse_netns);
9266 cfg_register_section("resolvers", cfg_parse_resolvers);
9267}
9268
David Carlier845efb52015-09-25 11:49:18 +01009269/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009270 * Local variables:
9271 * c-indent-level: 8
9272 * c-basic-offset: 8
9273 * End:
9274 */