blob: f16732191335a821bf3afe0ce4a3abff3804752d [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 }
Olivier Houchard1fc05162017-04-06 01:05:05 +0200662 else if (!strcmp(args[0], "no-unused-socket")) {
663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
665 global.tune.options &= ~GTUNE_SOCKET_TRANSFER;
666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 global.mode |= MODE_QUIET;
671 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 if (global.tune.maxpollevents != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 }
685 global.tune.maxpollevents = atol(args[1]);
686 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200688 if (alertif_too_many_args(1, file, linenum, args, &err_code))
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 if (global.tune.maxaccept != 0) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 }
700 global.tune.maxaccept = atol(args[1]);
701 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
704 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 global.tune.chksize = atol(args[1]);
711 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100712 else if (!strcmp(args[0], "tune.recv_enough")) {
713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.recv_enough = atol(args[1]);
721 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100722 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200723 if (alertif_too_many_args(1, file, linenum, args, &err_code))
724 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730 global.tune.buf_limit = atol(args[1]);
731 if (global.tune.buf_limit) {
732 if (global.tune.buf_limit < 3)
733 global.tune.buf_limit = 3;
734 if (global.tune.buf_limit <= global.tune.reserved_bufs)
735 global.tune.buf_limit = global.tune.reserved_bufs + 1;
736 }
737 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100738 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200739 if (alertif_too_many_args(1, file, linenum, args, &err_code))
740 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746 global.tune.reserved_bufs = atol(args[1]);
747 if (global.tune.reserved_bufs < 2)
748 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100749 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
750 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100751 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200752 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200753 if (alertif_too_many_args(1, file, linenum, args, &err_code))
754 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200755 if (*(args[1]) == 0) {
756 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200761 if (global.tune.bufsize <= 0) {
762 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100766 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100767 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200768 }
769 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200770 if (alertif_too_many_args(1, file, linenum, args, &err_code))
771 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200772 if (*(args[1]) == 0) {
773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
776 }
777 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200778 if (global.tune.maxrewrite < 0) {
779 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200783 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100784 else if (!strcmp(args[0], "tune.idletimer")) {
785 unsigned int idle;
786 const char *res;
787
William Lallemand1a748ae2015-05-19 16:37:23 +0200788 if (alertif_too_many_args(1, file, linenum, args, &err_code))
789 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795
796 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
797 if (res) {
798 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
799 file, linenum, *res, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803
804 if (idle > 65535) {
805 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 global.tune.idle_timer = idle;
810 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100811 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200812 if (alertif_too_many_args(1, file, linenum, args, &err_code))
813 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100814 if (global.tune.client_rcvbuf != 0) {
815 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT;
817 goto out;
818 }
819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824 global.tune.client_rcvbuf = atol(args[1]);
825 }
826 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200827 if (alertif_too_many_args(1, file, linenum, args, &err_code))
828 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100829 if (global.tune.server_rcvbuf != 0) {
830 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT;
832 goto out;
833 }
834 if (*(args[1]) == 0) {
835 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT | ERR_FATAL;
837 goto out;
838 }
839 global.tune.server_rcvbuf = atol(args[1]);
840 }
841 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200842 if (alertif_too_many_args(1, file, linenum, args, &err_code))
843 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100844 if (global.tune.client_sndbuf != 0) {
845 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT;
847 goto out;
848 }
849 if (*(args[1]) == 0) {
850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 global.tune.client_sndbuf = atol(args[1]);
855 }
856 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200857 if (alertif_too_many_args(1, file, linenum, args, &err_code))
858 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100859 if (global.tune.server_sndbuf != 0) {
860 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT;
862 goto out;
863 }
864 if (*(args[1]) == 0) {
865 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868 }
869 global.tune.server_sndbuf = atol(args[1]);
870 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200871 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200872 if (alertif_too_many_args(1, file, linenum, args, &err_code))
873 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.tune.pipesize = atol(args[1]);
880 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100881 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200882 if (alertif_too_many_args(1, file, linenum, args, &err_code))
883 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.tune.cookie_len = atol(args[1]) + 1;
890 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200891 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
893 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 global.tune.max_http_hdr = atol(args[1]);
900 }
William Lallemandf3747832012-11-09 12:33:10 +0100901 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
903 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100904 if (*args[1]) {
905 global.tune.comp_maxlevel = atoi(args[1]);
906 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
907 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
908 file, linenum, args[0]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911 }
912 } else {
913 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
914 file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200919 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
920 if (*args[1]) {
921 global.tune.pattern_cache = atoi(args[1]);
922 if (global.tune.pattern_cache < 0) {
923 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
924 file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 } else {
929 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
930 file, linenum, args[0]);
931 err_code |= ERR_ALERT | ERR_FATAL;
932 goto out;
933 }
934 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200936 if (alertif_too_many_args(1, file, linenum, args, &err_code))
937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200939 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 if (*(args[1]) == 0) {
944 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200945 err_code |= ERR_ALERT | ERR_FATAL;
946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100948 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
949 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]);
950 err_code |= ERR_WARN;
951 goto out;
952 }
953
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 }
955 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200959 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100968 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
969 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]);
970 err_code |= ERR_WARN;
971 goto out;
972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
Simon Horman98637e52014-06-20 12:30:16 +0900974 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200975 if (alertif_too_many_args(0, file, linenum, args, &err_code))
976 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900977 global.external_check = 1;
978 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200979 /* user/group name handling */
980 else if (!strcmp(args[0], "user")) {
981 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200982 if (alertif_too_many_args(1, file, linenum, args, &err_code))
983 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200984 if (global.uid != 0) {
985 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200988 }
989 errno = 0;
990 ha_user = getpwnam(args[1]);
991 if (ha_user != NULL) {
992 global.uid = (int)ha_user->pw_uid;
993 }
994 else {
995 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 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200997 }
998 }
999 else if (!strcmp(args[0], "group")) {
1000 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001001 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1002 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001003 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001004 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT;
1006 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001007 }
1008 errno = 0;
1009 ha_group = getgrnam(args[1]);
1010 if (ha_group != NULL) {
1011 global.gid = (int)ha_group->gr_gid;
1012 }
1013 else {
1014 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 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001016 }
1017 }
1018 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 if (*(args[1]) == 0) {
1023 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 }
1027 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001028 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1029 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1030 file, linenum, args[0], LONGBITS, global.nbproc);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 }
1035 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001036 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 if (global.maxconn != 0) {
1039 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT;
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 if (*(args[1]) == 0) {
1044 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 }
1048 global.maxconn = atol(args[1]);
1049#ifdef SYSTEM_MAXCONN
1050 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1051 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);
1052 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055#endif /* SYSTEM_MAXCONN */
1056 }
Emeric Brun850efd52014-01-29 12:24:34 +01001057 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001058 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1059 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001060 if (*(args[1]) == 0) {
1061 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 if (strcmp(args[1],"none") == 0)
1066 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1067 else if (strcmp(args[1],"required") == 0)
1068 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1069 else {
1070 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001075 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001076 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1077 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001078 if (global.cps_lim != 0) {
1079 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT;
1081 goto out;
1082 }
1083 if (*(args[1]) == 0) {
1084 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088 global.cps_lim = atol(args[1]);
1089 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001090 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001091 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1092 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001093 if (global.sps_lim != 0) {
1094 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT;
1096 goto out;
1097 }
1098 if (*(args[1]) == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto out;
1102 }
1103 global.sps_lim = atol(args[1]);
1104 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001105 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001106 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1107 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001108 if (global.ssl_lim != 0) {
1109 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT;
1111 goto out;
1112 }
1113 if (*(args[1]) == 0) {
1114 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT | ERR_FATAL;
1116 goto out;
1117 }
1118 global.ssl_lim = atol(args[1]);
1119 }
William Lallemandd85f9172012-11-09 17:05:39 +01001120 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001121 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1122 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001123 if (*(args[1]) == 0) {
1124 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128 global.comp_rate_lim = atoi(args[1]) * 1024;
1129 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001130 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001131 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1132 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001133 if (global.maxpipes != 0) {
1134 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001137 }
1138 if (*(args[1]) == 0) {
1139 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001142 }
1143 global.maxpipes = atol(args[1]);
1144 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001145 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001146 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1147 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001148 if (*(args[1]) == 0) {
1149 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto out;
1152 }
William Lallemande3a7d992012-11-20 11:25:20 +01001153 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001154 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001155 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001156 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1157 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001158 if (*(args[1]) == 0) {
1159 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto out;
1162 }
1163 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001164 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001165 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
1168 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001169 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001170
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001172 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 if (global.rlimit_nofile != 0) {
1175 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 if (*(args[1]) == 0) {
1180 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 }
1184 global.rlimit_nofile = atol(args[1]);
1185 }
1186 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001187 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001189 if (global.chroot != NULL) {
1190 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
1194 if (*(args[1]) == 0) {
1195 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 }
1199 global.chroot = strdup(args[1]);
1200 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001201 else if (!strcmp(args[0], "description")) {
1202 int i, len=0;
1203 char *d;
1204
1205 if (!*args[1]) {
1206 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1207 file, linenum, args[0]);
1208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
1210 }
1211
Willy Tarreau348acfe2014-04-14 15:00:39 +02001212 for (i = 1; *args[i]; i++)
1213 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001214
1215 if (global.desc)
1216 free(global.desc);
1217
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001218 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001219
Willy Tarreau348acfe2014-04-14 15:00:39 +02001220 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1221 for (i = 2; *args[i]; i++)
1222 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001223 }
1224 else if (!strcmp(args[0], "node")) {
1225 int i;
1226 char c;
1227
William Lallemand1a748ae2015-05-19 16:37:23 +02001228 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1229 goto out;
1230
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001231 for (i=0; args[1][i]; i++) {
1232 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001233 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1234 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001235 break;
1236 }
1237
1238 if (!i || args[1][i]) {
1239 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1240 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1241 file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245
1246 if (global.node)
1247 free(global.node);
1248
1249 global.node = strdup(args[1]);
1250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001252 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001254 if (global.pidfile != NULL) {
1255 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT;
1257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 if (*(args[1]) == 0) {
1260 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 }
1264 global.pidfile = strdup(args[1]);
1265 }
Emeric Bruned760922010-10-22 17:59:25 +02001266 else if (!strcmp(args[0], "unix-bind")) {
1267 int cur_arg = 1;
1268 while (*(args[cur_arg])) {
1269 if (!strcmp(args[cur_arg], "prefix")) {
1270 if (global.unix_bind.prefix != NULL) {
1271 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1272 err_code |= ERR_ALERT;
1273 cur_arg += 2;
1274 continue;
1275 }
1276
1277 if (*(args[cur_arg+1]) == 0) {
1278 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281 }
1282 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1283 cur_arg += 2;
1284 continue;
1285 }
1286
1287 if (!strcmp(args[cur_arg], "mode")) {
1288
1289 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1290 cur_arg += 2;
1291 continue;
1292 }
1293
1294 if (!strcmp(args[cur_arg], "uid")) {
1295
1296 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1297 cur_arg += 2;
1298 continue;
1299 }
1300
1301 if (!strcmp(args[cur_arg], "gid")) {
1302
1303 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1304 cur_arg += 2;
1305 continue;
1306 }
1307
1308 if (!strcmp(args[cur_arg], "user")) {
1309 struct passwd *user;
1310
1311 user = getpwnam(args[cur_arg + 1]);
1312 if (!user) {
1313 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1314 file, linenum, args[0], args[cur_arg + 1 ]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
1319 global.unix_bind.ux.uid = user->pw_uid;
1320 cur_arg += 2;
1321 continue;
1322 }
1323
1324 if (!strcmp(args[cur_arg], "group")) {
1325 struct group *group;
1326
1327 group = getgrnam(args[cur_arg + 1]);
1328 if (!group) {
1329 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1330 file, linenum, args[0], args[cur_arg + 1 ]);
1331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
1333 }
1334
1335 global.unix_bind.ux.gid = group->gr_gid;
1336 cur_arg += 2;
1337 continue;
1338 }
1339
Willy Tarreaub48f9582011-09-05 01:17:06 +02001340 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001341 file, linenum, args[0]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345 }
William Lallemand0f99e342011-10-12 17:50:54 +02001346 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1347 /* delete previous herited or defined syslog servers */
1348 struct logsrv *back;
1349 struct logsrv *tmp;
1350
1351 if (*(args[1]) != 0) {
1352 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356
1357 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1358 LIST_DEL(&tmp->list);
1359 free(tmp);
1360 }
1361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001363 struct sockaddr_storage *sk;
1364 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001365 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001366 int arg = 0;
1367 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001368
William Lallemand1a748ae2015-05-19 16:37:23 +02001369 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1370 goto out;
1371
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372 if (*(args[1]) == 0 || *(args[2]) == 0) {
1373 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
William Lallemand0f99e342011-10-12 17:50:54 +02001377
Vincent Bernat02779b62016-04-03 13:48:43 +02001378 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001379
Willy Tarreau18324f52014-06-27 18:10:07 +02001380 /* just after the address, a length may be specified */
1381 if (strcmp(args[arg+2], "len") == 0) {
1382 len = atoi(args[arg+3]);
1383 if (len < 80 || len > 65535) {
1384 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1385 file, linenum, args[arg+3]);
1386 err_code |= ERR_ALERT | ERR_FATAL;
1387 goto out;
1388 }
1389 logsrv->maxlen = len;
1390
1391 /* skip these two args */
1392 arg += 2;
1393 }
1394 else
1395 logsrv->maxlen = MAX_SYSLOG_LEN;
1396
1397 if (logsrv->maxlen > global.max_syslog_len) {
1398 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001399 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1400 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1401 logline = my_realloc2(logline, global.max_syslog_len + 1);
1402 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001403 }
1404
Dragan Dosen1322d092015-09-22 16:05:32 +02001405 /* after the length, a format may be specified */
1406 if (strcmp(args[arg+2], "format") == 0) {
1407 logsrv->format = get_log_format(args[arg+3]);
1408 if (logsrv->format < 0) {
1409 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001411 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001412 goto out;
1413 }
1414
1415 /* skip these two args */
1416 arg += 2;
1417 }
1418
David Carlier97880bb2016-04-08 10:35:26 +01001419 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1420 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001421 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001422 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001423
Willy Tarreau18324f52014-06-27 18:10:07 +02001424 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001425 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001426 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001427 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001428 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 }
1430
William Lallemand0f99e342011-10-12 17:50:54 +02001431 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001432 if (*(args[arg+3])) {
1433 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001434 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001435 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001437 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
1439 }
1440
William Lallemand0f99e342011-10-12 17:50:54 +02001441 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001442 if (*(args[arg+4])) {
1443 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001444 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001445 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001447 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001448 }
1449 }
1450
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001451 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001452 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001453 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001454 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001455 free(logsrv);
1456 goto out;
1457 }
1458 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001459
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001460 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001461 if (port1 != port2) {
1462 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1463 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001464 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001465 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001466 goto out;
1467 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001468
William Lallemand0f99e342011-10-12 17:50:54 +02001469 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001470 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001471 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473
William Lallemand0f99e342011-10-12 17:50:54 +02001474 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001475 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001476 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1477 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001478
1479 if (global.log_send_hostname != NULL) {
1480 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1481 err_code |= ERR_ALERT;
1482 goto out;
1483 }
1484
1485 if (*(args[1]))
1486 name = args[1];
1487 else
1488 name = hostname;
1489
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001490 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001491 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001492 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001493 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1494 if (global.server_state_base != NULL) {
1495 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1496 err_code |= ERR_ALERT;
1497 goto out;
1498 }
1499
1500 if (!*(args[1])) {
1501 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1502 err_code |= ERR_FATAL;
1503 goto out;
1504 }
1505
1506 global.server_state_base = strdup(args[1]);
1507 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001508 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1509 if (global.server_state_file != NULL) {
1510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1511 err_code |= ERR_ALERT;
1512 goto out;
1513 }
1514
1515 if (!*(args[1])) {
1516 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1517 err_code |= ERR_FATAL;
1518 goto out;
1519 }
1520
1521 global.server_state_file = strdup(args[1]);
1522 }
Kevinm48936af2010-12-22 16:08:21 +00001523 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001524 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1525 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001526 if (*(args[1]) == 0) {
1527 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
1530 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001531 chunk_destroy(&global.log_tag);
1532 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001533 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001534 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001535 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1536 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001537 if (global.spread_checks != 0) {
1538 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001539 err_code |= ERR_ALERT;
1540 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001541 }
1542 if (*(args[1]) == 0) {
1543 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001546 }
1547 global.spread_checks = atol(args[1]);
1548 if (global.spread_checks < 0 || global.spread_checks > 50) {
1549 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001553 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1554 const char *err;
1555 unsigned int val;
1556
William Lallemand1a748ae2015-05-19 16:37:23 +02001557 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1558 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001559 if (*(args[1]) == 0) {
1560 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
1563 }
1564
1565 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1566 if (err) {
1567 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1568 err_code |= ERR_ALERT | ERR_FATAL;
1569 }
1570 global.max_spread_checks = val;
1571 if (global.max_spread_checks < 0) {
1572 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1573 err_code |= ERR_ALERT | ERR_FATAL;
1574 }
1575 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001576 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1577#ifdef USE_CPU_AFFINITY
1578 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001579 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001580 unsigned long cpus = 0;
1581
1582 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001583 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001584 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001585 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001586 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001587 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001588 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001589 proc = atol(args[1]);
1590 if (proc >= 1 && proc <= LONGBITS)
1591 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001592 }
1593
1594 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001595 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",
1596 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
1599 }
1600
1601 cur_arg = 2;
1602 while (*args[cur_arg]) {
1603 unsigned int low, high;
1604
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001605 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001606 char *dash = strchr(args[cur_arg], '-');
1607
1608 low = high = str2uic(args[cur_arg]);
1609 if (dash)
1610 high = str2uic(dash + 1);
1611
1612 if (high < low) {
1613 unsigned int swap = low;
1614 low = high;
1615 high = swap;
1616 }
1617
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001618 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001619 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001620 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
1623 }
1624
1625 while (low <= high)
1626 cpus |= 1UL << low++;
1627 }
1628 else {
1629 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1630 file, linenum, args[0], args[cur_arg]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
1634 cur_arg++;
1635 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001636 for (i = 0; i < LONGBITS; i++)
1637 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001638 global.cpu_map[i] = cpus;
1639#else
1640 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
1643#endif
1644 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001645 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1646 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1647 goto out;
1648
1649 if (*(args[2]) == 0) {
1650 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
1653 }
1654
1655 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1656 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1657 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
1660 }
1661 }
1662 else if (!strcmp(args[0], "unsetenv")) {
1663 int arg;
1664
1665 if (*(args[1]) == 0) {
1666 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669 }
1670
1671 for (arg = 1; *args[arg]; arg++) {
1672 if (unsetenv(args[arg]) != 0) {
1673 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
1676 }
1677 }
1678 }
1679 else if (!strcmp(args[0], "resetenv")) {
1680 extern char **environ;
1681 char **env = environ;
1682
1683 /* args contain variable names to keep, one per argument */
1684 while (*env) {
1685 int arg;
1686
1687 /* look for current variable in among all those we want to keep */
1688 for (arg = 1; *args[arg]; arg++) {
1689 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1690 (*env)[strlen(args[arg])] == '=')
1691 break;
1692 }
1693
1694 /* delete this variable */
1695 if (!*args[arg]) {
1696 char *delim = strchr(*env, '=');
1697
1698 if (!delim || delim - *env >= trash.size) {
1699 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
1702 }
1703
1704 memcpy(trash.str, *env, delim - *env);
1705 trash.str[delim - *env] = 0;
1706
1707 if (unsetenv(trash.str) != 0) {
1708 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
1711 }
1712 }
1713 else
1714 env++;
1715 }
1716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001718 struct cfg_kw_list *kwl;
1719 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001720 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001721
1722 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1723 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1724 if (kwl->kw[index].section != CFG_GLOBAL)
1725 continue;
1726 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001727 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001728 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001729 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001731 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001732 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001733 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001734 err_code |= ERR_WARN;
1735 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001736 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001737 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001738 }
1739 }
1740 }
1741
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001745
Willy Tarreau058e9072009-07-20 09:30:05 +02001746 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001747 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001748 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749}
1750
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001751void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001753 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 defproxy.mode = PR_MODE_TCP;
1755 defproxy.state = PR_STNEW;
1756 defproxy.maxconn = cfg_maxpconn;
1757 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001758 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001759 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001760
Simon Horman66183002013-02-23 10:16:43 +09001761 defproxy.defsrv.check.inter = DEF_CHKINTR;
1762 defproxy.defsrv.check.fastinter = 0;
1763 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001764 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1765 defproxy.defsrv.agent.fastinter = 0;
1766 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001767 defproxy.defsrv.check.rise = DEF_RISETIME;
1768 defproxy.defsrv.check.fall = DEF_FALLTIME;
1769 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1770 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001771 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001772 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001773 defproxy.defsrv.maxqueue = 0;
1774 defproxy.defsrv.minconn = 0;
1775 defproxy.defsrv.maxconn = 0;
1776 defproxy.defsrv.slowstart = 0;
1777 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1778 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1779 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001780
1781 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001782 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783}
1784
Willy Tarreauade5ec42010-01-28 19:33:49 +01001785
Willy Tarreau63af98d2014-05-18 08:11:41 +02001786/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1787 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1788 * ERR_FATAL in case of error.
1789 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001790static int create_cond_regex_rule(const char *file, int line,
1791 struct proxy *px, int dir, int action, int flags,
1792 const char *cmd, const char *reg, const char *repl,
1793 const char **cond_start)
1794{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001795 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001796 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001797 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001798 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001799 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001800 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001801 int cs;
1802 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001803
1804 if (px == &defproxy) {
1805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001806 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001807 goto err;
1808 }
1809
1810 if (*reg == 0) {
1811 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001813 goto err;
1814 }
1815
Christopher Faulet898566e2016-10-26 11:06:28 +02001816 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001817 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001818
Willy Tarreau5321c422010-01-28 20:35:13 +01001819 if (cond_start &&
1820 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001821 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1822 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1823 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001824 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001825 goto err;
1826 }
1827 }
1828 else if (cond_start && **cond_start) {
1829 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1830 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001831 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001832 goto err;
1833 }
1834
Willy Tarreau63af98d2014-05-18 08:11:41 +02001835 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001836 (dir == SMP_OPT_DIR_REQ) ?
1837 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1838 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1839 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001840
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001841 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001842 if (!preg) {
1843 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001844 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001845 goto err;
1846 }
1847
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001848 cs = !(flags & REG_ICASE);
1849 cap = !(flags & REG_NOSUB);
1850 error = NULL;
1851 if (!regex_comp(reg, preg, cs, cap, &error)) {
1852 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1853 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001854 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001855 goto err;
1856 }
1857
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001858 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001859 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001860 if (repl && err) {
1861 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1862 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code |= ERR_ALERT | ERR_FATAL;
1864 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001865 }
1866
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001867 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001868 ret_code |= ERR_WARN;
1869
1870 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001871
Willy Tarreau63af98d2014-05-18 08:11:41 +02001872 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001873 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001874 err:
1875 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001876 free(errmsg);
1877 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001878}
1879
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880/*
William Lallemand51097192015-04-14 16:35:22 +02001881 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001882 * Returns the error code, 0 if OK, or any combination of :
1883 * - ERR_ABORT: must abort ASAP
1884 * - ERR_FATAL: we can continue parsing but not start the service
1885 * - ERR_WARN: a warning has been emitted
1886 * - ERR_ALERT: an alert has been emitted
1887 * Only the two first ones can stop processing, the two others are just
1888 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001890int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1891{
1892 static struct peers *curpeers = NULL;
1893 struct peer *newpeer = NULL;
1894 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001895 struct bind_conf *bind_conf;
1896 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001897 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001898 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001899
1900 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001901 if (!*args[1]) {
1902 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001903 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001904 goto out;
1905 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001906
William Lallemand6e62fb62015-04-28 16:55:23 +02001907 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1908 goto out;
1909
Emeric Brun32da3c42010-09-23 18:39:19 +02001910 err = invalid_char(args[1]);
1911 if (err) {
1912 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1913 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001914 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001915 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001916 }
1917
1918 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1919 /*
1920 * If there are two proxies with the same name only following
1921 * combinations are allowed:
1922 */
1923 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001924 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 +02001925 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001927 }
1928 }
1929
Vincent Bernat02779b62016-04-03 13:48:43 +02001930 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001931 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1932 err_code |= ERR_ALERT | ERR_ABORT;
1933 goto out;
1934 }
1935
1936 curpeers->next = peers;
1937 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001938 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001939 curpeers->conf.line = linenum;
1940 curpeers->last_change = now.tv_sec;
1941 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001942 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001943 }
1944 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001945 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001946 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001947 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001948
1949 if (!*args[2]) {
1950 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1951 file, linenum, args[0]);
1952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
1954 }
1955
1956 err = invalid_char(args[1]);
1957 if (err) {
1958 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1959 file, linenum, *err, args[1]);
1960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
1962 }
1963
Vincent Bernat02779b62016-04-03 13:48:43 +02001964 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001965 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1966 err_code |= ERR_ALERT | ERR_ABORT;
1967 goto out;
1968 }
1969
1970 /* the peers are linked backwards first */
1971 curpeers->count++;
1972 newpeer->next = curpeers->remote;
1973 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001974 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001975 newpeer->conf.line = linenum;
1976
1977 newpeer->last_change = now.tv_sec;
1978 newpeer->id = strdup(args[1]);
1979
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001980 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001981 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001982 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001985 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001986
1987 proto = protocol_by_family(sk->ss_family);
1988 if (!proto || !proto->connect) {
1989 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1990 file, linenum, args[0], args[1]);
1991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
1993 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001994
1995 if (port1 != port2) {
1996 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1997 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
2000 }
2001
Willy Tarreau2aa38802013-02-20 19:20:59 +01002002 if (!port1) {
2003 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2004 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002005 err_code |= ERR_ALERT | ERR_FATAL;
2006 goto out;
2007 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002010 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002011 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002012 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002013
Emeric Brun32da3c42010-09-23 18:39:19 +02002014 if (strcmp(newpeer->id, localpeer) == 0) {
2015 /* Current is local peer, it define a frontend */
2016 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002017 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002018
2019 if (!curpeers->peers_fe) {
2020 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2021 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2022 err_code |= ERR_ALERT | ERR_ABORT;
2023 goto out;
2024 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002025
Willy Tarreau237250c2011-07-29 01:49:03 +02002026 init_new_proxy(curpeers->peers_fe);
2027 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002028 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002029 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2030 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002031 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002032
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002033 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002034
Willy Tarreau902636f2013-03-10 19:44:48 +01002035 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2036 if (errmsg && *errmsg) {
2037 indent_msg(&errmsg, 2);
2038 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002039 }
2040 else
2041 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2042 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002043 err_code |= ERR_FATAL;
2044 goto out;
2045 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002046
2047 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002048 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002049 l->maxconn = curpeers->peers_fe->maxconn;
2050 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002051 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002052 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002053 l->analysers |= curpeers->peers_fe->fe_req_ana;
2054 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002055 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2056 global.maxsock += l->maxconn;
2057 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002058 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002059 else {
2060 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2061 file, linenum, args[0], args[1],
2062 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2063 err_code |= ERR_FATAL;
2064 goto out;
2065 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002066 }
2067 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002068 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2069 curpeers->state = PR_STSTOPPED;
2070 }
2071 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2072 curpeers->state = PR_STNEW;
2073 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002074 else if (*args[0] != 0) {
2075 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
2078 }
2079
2080out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002082 return err_code;
2083}
2084
Baptiste Assmann325137d2015-04-13 23:40:55 +02002085/*
2086 * Parse a <resolvers> section.
2087 * Returns the error code, 0 if OK, or any combination of :
2088 * - ERR_ABORT: must abort ASAP
2089 * - ERR_FATAL: we can continue parsing but not start the service
2090 * - ERR_WARN: a warning has been emitted
2091 * - ERR_ALERT: an alert has been emitted
2092 * Only the two first ones can stop processing, the two others are just
2093 * indicators.
2094 */
2095int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2096{
2097 static struct dns_resolvers *curr_resolvers = NULL;
2098 struct dns_nameserver *newnameserver = NULL;
2099 const char *err;
2100 int err_code = 0;
2101 char *errmsg = NULL;
2102
2103 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2104 if (!*args[1]) {
2105 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2106 err_code |= ERR_ALERT | ERR_ABORT;
2107 goto out;
2108 }
2109
2110 err = invalid_char(args[1]);
2111 if (err) {
2112 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2113 file, linenum, *err, args[0], args[1]);
2114 err_code |= ERR_ALERT | ERR_ABORT;
2115 goto out;
2116 }
2117
2118 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2119 /* Error if two resolvers owns the same name */
2120 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2121 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2122 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2123 err_code |= ERR_ALERT | ERR_ABORT;
2124 }
2125 }
2126
Vincent Bernat02779b62016-04-03 13:48:43 +02002127 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2129 err_code |= ERR_ALERT | ERR_ABORT;
2130 goto out;
2131 }
2132
2133 /* default values */
2134 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2135 curr_resolvers->conf.file = strdup(file);
2136 curr_resolvers->conf.line = linenum;
2137 curr_resolvers->id = strdup(args[1]);
2138 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002139 /* default hold period for nx, other, refuse and timeout is 30s */
2140 curr_resolvers->hold.nx = 30000;
2141 curr_resolvers->hold.other = 30000;
2142 curr_resolvers->hold.refused = 30000;
2143 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002144 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002145 curr_resolvers->hold.valid = 10000;
2146 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002147 curr_resolvers->resolve_retries = 3;
2148 LIST_INIT(&curr_resolvers->nameserver_list);
2149 LIST_INIT(&curr_resolvers->curr_resolution);
2150 }
2151 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2152 struct sockaddr_storage *sk;
2153 int port1, port2;
2154 struct protocol *proto;
2155
2156 if (!*args[2]) {
2157 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2158 file, linenum, args[0]);
2159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
2161 }
2162
2163 err = invalid_char(args[1]);
2164 if (err) {
2165 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2166 file, linenum, *err, args[1]);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
Baptiste Assmanna315c552015-11-02 22:55:49 +01002171 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2172 /* Error if two resolvers owns the same name */
2173 if (strcmp(newnameserver->id, args[1]) == 0) {
2174 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2175 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 }
2178 }
2179
Vincent Bernat02779b62016-04-03 13:48:43 +02002180 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002181 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2182 err_code |= ERR_ALERT | ERR_ABORT;
2183 goto out;
2184 }
2185
2186 /* the nameservers are linked backward first */
2187 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2188 curr_resolvers->count_nameservers++;
2189 newnameserver->resolvers = curr_resolvers;
2190 newnameserver->conf.file = strdup(file);
2191 newnameserver->conf.line = linenum;
2192 newnameserver->id = strdup(args[1]);
2193
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002194 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002195 if (!sk) {
2196 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
2201 proto = protocol_by_family(sk->ss_family);
2202 if (!proto || !proto->connect) {
2203 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2204 file, linenum, args[0], args[1]);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208
2209 if (port1 != port2) {
2210 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2211 file, linenum, args[0], args[1], args[2]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
2215
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002216 if (!port1 && !port2) {
2217 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2218 file, linenum, args[0], args[1]);
2219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
2221 }
2222
Baptiste Assmann325137d2015-04-13 23:40:55 +02002223 newnameserver->addr = *sk;
2224 }
2225 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2226 const char *res;
2227 unsigned int time;
2228
2229 if (!*args[2]) {
2230 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2231 file, linenum, args[0]);
2232 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2237 if (res) {
2238 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2239 file, linenum, *res, args[0]);
2240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
2242 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002243 if (strcmp(args[1], "nx") == 0)
2244 curr_resolvers->hold.nx = time;
2245 else if (strcmp(args[1], "other") == 0)
2246 curr_resolvers->hold.other = time;
2247 else if (strcmp(args[1], "refused") == 0)
2248 curr_resolvers->hold.refused = time;
2249 else if (strcmp(args[1], "timeout") == 0)
2250 curr_resolvers->hold.timeout = time;
2251 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002252 curr_resolvers->hold.valid = time;
2253 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002254 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2255 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
2258 }
2259
2260 }
2261 else if (strcmp(args[0], "resolve_retries") == 0) {
2262 if (!*args[1]) {
2263 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2264 file, linenum, args[0]);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
2268 curr_resolvers->resolve_retries = atoi(args[1]);
2269 }
2270 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002271 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002272 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2273 file, linenum, args[0]);
2274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
2276 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002277 else if (strcmp(args[1], "retry") == 0) {
2278 const char *res;
2279 unsigned int timeout_retry;
2280
2281 if (!*args[2]) {
2282 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2283 file, linenum, args[0], args[1]);
2284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
2286 }
2287 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2288 if (res) {
2289 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2290 file, linenum, *res, args[0], args[1]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294 curr_resolvers->timeout.retry = timeout_retry;
2295 }
2296 else {
2297 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2298 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
2301 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002302 } /* neither "nameserver" nor "resolvers" */
2303 else if (*args[0] != 0) {
2304 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308
2309 out:
2310 free(errmsg);
2311 return err_code;
2312}
Simon Horman0d16a402015-01-30 11:22:58 +09002313
2314/*
William Lallemand51097192015-04-14 16:35:22 +02002315 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002316 * Returns the error code, 0 if OK, or any combination of :
2317 * - ERR_ABORT: must abort ASAP
2318 * - ERR_FATAL: we can continue parsing but not start the service
2319 * - ERR_WARN: a warning has been emitted
2320 * - ERR_ALERT: an alert has been emitted
2321 * Only the two first ones can stop processing, the two others are just
2322 * indicators.
2323 */
2324int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2325{
2326 static struct mailers *curmailers = NULL;
2327 struct mailer *newmailer = NULL;
2328 const char *err;
2329 int err_code = 0;
2330 char *errmsg = NULL;
2331
2332 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2333 if (!*args[1]) {
2334 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2335 err_code |= ERR_ALERT | ERR_ABORT;
2336 goto out;
2337 }
2338
2339 err = invalid_char(args[1]);
2340 if (err) {
2341 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2342 file, linenum, *err, args[0], args[1]);
2343 err_code |= ERR_ALERT | ERR_ABORT;
2344 goto out;
2345 }
2346
2347 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2348 /*
2349 * If there are two proxies with the same name only following
2350 * combinations are allowed:
2351 */
2352 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002353 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 +09002354 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002355 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002356 }
2357 }
2358
Vincent Bernat02779b62016-04-03 13:48:43 +02002359 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2361 err_code |= ERR_ALERT | ERR_ABORT;
2362 goto out;
2363 }
2364
2365 curmailers->next = mailers;
2366 mailers = curmailers;
2367 curmailers->conf.file = strdup(file);
2368 curmailers->conf.line = linenum;
2369 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002370 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2371 * But need enough time so that timeouts don't occur
2372 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002373 }
2374 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2375 struct sockaddr_storage *sk;
2376 int port1, port2;
2377 struct protocol *proto;
2378
2379 if (!*args[2]) {
2380 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2381 file, linenum, args[0]);
2382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
2384 }
2385
2386 err = invalid_char(args[1]);
2387 if (err) {
2388 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2389 file, linenum, *err, args[1]);
2390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
2392 }
2393
Vincent Bernat02779b62016-04-03 13:48:43 +02002394 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002395 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2396 err_code |= ERR_ALERT | ERR_ABORT;
2397 goto out;
2398 }
2399
2400 /* the mailers are linked backwards first */
2401 curmailers->count++;
2402 newmailer->next = curmailers->mailer_list;
2403 curmailers->mailer_list = newmailer;
2404 newmailer->mailers = curmailers;
2405 newmailer->conf.file = strdup(file);
2406 newmailer->conf.line = linenum;
2407
2408 newmailer->id = strdup(args[1]);
2409
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002410 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002411 if (!sk) {
2412 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
2415 }
2416
2417 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002418 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2419 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002420 file, linenum, args[0], args[1]);
2421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
2423 }
2424
2425 if (port1 != port2) {
2426 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2427 file, linenum, args[0], args[1], args[2]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431
2432 if (!port1) {
2433 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2434 file, linenum, args[0], args[1], args[2]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438
2439 newmailer->addr = *sk;
2440 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002441 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002442 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002443 }
2444 else if (strcmp(args[0], "timeout") == 0) {
2445 if (!*args[1]) {
2446 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2447 file, linenum, args[0]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451 else if (strcmp(args[1], "mail") == 0) {
2452 const char *res;
2453 unsigned int timeout_mail;
2454 if (!*args[2]) {
2455 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2456 file, linenum, args[0], args[1]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2461 if (res) {
2462 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2463 file, linenum, *res, args[0]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467 if (timeout_mail <= 0) {
2468 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
2472 curmailers->timeout.mail = timeout_mail;
2473 } else {
2474 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2475 file, linenum, args[0], args[1]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479 }
Simon Horman0d16a402015-01-30 11:22:58 +09002480 else if (*args[0] != 0) {
2481 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486out:
2487 free(errmsg);
2488 return err_code;
2489}
2490
Simon Horman9dc49962015-01-30 11:22:59 +09002491static void free_email_alert(struct proxy *p)
2492{
2493 free(p->email_alert.mailers.name);
2494 p->email_alert.mailers.name = NULL;
2495 free(p->email_alert.from);
2496 p->email_alert.from = NULL;
2497 free(p->email_alert.to);
2498 p->email_alert.to = NULL;
2499 free(p->email_alert.myhostname);
2500 p->email_alert.myhostname = NULL;
2501}
2502
Willy Tarreau3842f002009-06-14 11:39:52 +02002503int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504{
2505 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002506 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002507 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002508 int rc;
2509 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002510 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002511 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002512 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002513 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002514 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515
Willy Tarreau977b8e42006-12-29 14:19:17 +01002516 if (!strcmp(args[0], "listen"))
2517 rc = PR_CAP_LISTEN;
2518 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002519 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002520 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002521 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002522 else
2523 rc = PR_CAP_NONE;
2524
2525 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 if (!*args[1]) {
2527 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002528 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_ABORT;
2531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002533
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002534 err = invalid_char(args[1]);
2535 if (err) {
2536 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2537 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002539 }
2540
Willy Tarreau8f50b682015-05-26 11:45:02 +02002541 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2542 if (curproxy) {
2543 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2544 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2545 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002547 }
2548
Vincent Bernat02779b62016-04-03 13:48:43 +02002549 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_ABORT;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002554
Willy Tarreau97cb7802010-01-03 20:23:58 +01002555 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 curproxy->next = proxy;
2557 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002558 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2559 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002560 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002563 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564
William Lallemand6e62fb62015-04-28 16:55:23 +02002565 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2566 if (curproxy->cap & PR_CAP_FE)
2567 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
2571 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002572 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002573 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002574
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002577 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002578 curproxy->no_options = defproxy.no_options;
2579 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002580 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002581 curproxy->except_net = defproxy.except_net;
2582 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002583 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002584 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002586 if (defproxy.fwdfor_hdr_len) {
2587 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2588 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2589 }
2590
Willy Tarreaub86db342009-11-30 11:50:16 +01002591 if (defproxy.orgto_hdr_len) {
2592 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2593 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2594 }
2595
Mark Lamourinec2247f02012-01-04 13:02:01 -05002596 if (defproxy.server_id_hdr_len) {
2597 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2598 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2599 }
2600
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 if (curproxy->cap & PR_CAP_FE) {
2602 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002603 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002604 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605
2606 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002607 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2608 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609
2610 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002614 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002615 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002616 curproxy->fullconn = defproxy.fullconn;
2617 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002618 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002619 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002621 if (defproxy.check_req) {
2622 curproxy->check_req = calloc(1, defproxy.check_len);
2623 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2624 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002625 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002627 if (defproxy.expect_str) {
2628 curproxy->expect_str = strdup(defproxy.expect_str);
2629 if (defproxy.expect_regex) {
2630 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002631 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2632 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002633 }
2634 }
2635
Willy Tarreau67402132012-05-31 20:40:20 +02002636 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002637 if (defproxy.cookie_name)
2638 curproxy->cookie_name = strdup(defproxy.cookie_name);
2639 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002640
2641 if (defproxy.dyncookie_key)
2642 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002643 if (defproxy.cookie_domain)
2644 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002645
Willy Tarreau31936852010-10-06 16:59:56 +02002646 if (defproxy.cookie_maxidle)
2647 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2648
2649 if (defproxy.cookie_maxlife)
2650 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2651
Emeric Brun647caf12009-06-30 17:57:00 +02002652 if (defproxy.rdp_cookie_name)
2653 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2654 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2655
Willy Tarreau01732802007-11-01 22:48:15 +01002656 if (defproxy.url_param_name)
2657 curproxy->url_param_name = strdup(defproxy.url_param_name);
2658 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002659
Benoitaffb4812009-03-25 13:02:10 +01002660 if (defproxy.hh_name)
2661 curproxy->hh_name = strdup(defproxy.hh_name);
2662 curproxy->hh_len = defproxy.hh_len;
2663 curproxy->hh_match_domain = defproxy.hh_match_domain;
2664
Willy Tarreauef9a3602012-12-08 22:29:20 +01002665 if (defproxy.conn_src.iface_name)
2666 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2667 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002668 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002669#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002670 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002671#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002672 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002675 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 if (defproxy.capture_name)
2677 curproxy->capture_name = strdup(defproxy.capture_name);
2678 curproxy->capture_namelen = defproxy.capture_namelen;
2679 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681
Willy Tarreau977b8e42006-12-29 14:19:17 +01002682 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002683 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002684 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002685 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002686 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002687 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002688 curproxy->mon_net = defproxy.mon_net;
2689 curproxy->mon_mask = defproxy.mon_mask;
2690 if (defproxy.monitor_uri)
2691 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2692 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002693 if (defproxy.defbe.name)
2694 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002695
2696 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002697 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2698 if (curproxy->conf.logformat_string &&
2699 curproxy->conf.logformat_string != default_http_log_format &&
2700 curproxy->conf.logformat_string != default_tcp_log_format &&
2701 curproxy->conf.logformat_string != clf_http_log_format)
2702 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2703
2704 if (defproxy.conf.lfs_file) {
2705 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2706 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2707 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002708
2709 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2710 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2711 if (curproxy->conf.logformat_sd_string &&
2712 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2713 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2714
2715 if (defproxy.conf.lfsd_file) {
2716 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2717 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2718 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002719 }
2720
2721 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002722 curproxy->timeout.connect = defproxy.timeout.connect;
2723 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002724 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002725 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002726 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002727 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002728 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002729 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002730 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002731 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 }
2733
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002735 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002736
2737 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002738 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002739 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002740 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002741 LIST_INIT(&node->list);
2742 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2743 }
2744
Willy Tarreau62a61232013-04-12 18:13:46 +02002745 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2746 if (curproxy->conf.uniqueid_format_string)
2747 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2748
Dragan Dosen43885c72015-10-01 13:18:13 +02002749 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002750
Willy Tarreau62a61232013-04-12 18:13:46 +02002751 if (defproxy.conf.uif_file) {
2752 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2753 curproxy->conf.uif_line = defproxy.conf.uif_line;
2754 }
William Lallemanda73203e2012-03-12 12:48:57 +01002755
2756 /* copy default header unique id */
2757 if (defproxy.header_unique_id)
2758 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2759
William Lallemand82fe75c2012-10-23 10:25:10 +02002760 /* default compression options */
2761 if (defproxy.comp != NULL) {
2762 curproxy->comp = calloc(1, sizeof(struct comp));
2763 curproxy->comp->algos = defproxy.comp->algos;
2764 curproxy->comp->types = defproxy.comp->types;
2765 }
2766
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002768 curproxy->conf.used_listener_id = EB_ROOT;
2769 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002770
Simon Horman98637e52014-06-20 12:30:16 +09002771 if (defproxy.check_path)
2772 curproxy->check_path = strdup(defproxy.check_path);
2773 if (defproxy.check_command)
2774 curproxy->check_command = strdup(defproxy.check_command);
2775
Simon Horman9dc49962015-01-30 11:22:59 +09002776 if (defproxy.email_alert.mailers.name)
2777 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2778 if (defproxy.email_alert.from)
2779 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2780 if (defproxy.email_alert.to)
2781 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2782 if (defproxy.email_alert.myhostname)
2783 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002784 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002785 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002786
Willy Tarreau93893792009-07-23 13:19:11 +02002787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 }
2789 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2790 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002791 /* FIXME-20070101: we should do this too at the end of the
2792 * config parsing to free all default values.
2793 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002794 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2795 err_code |= ERR_ABORT;
2796 goto out;
2797 }
2798
Willy Tarreaua534fea2008-08-03 12:19:50 +02002799 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002800 free(defproxy.check_command);
2801 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002802 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002803 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002804 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002805 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002806 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002807 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002808 free(defproxy.capture_name);
2809 free(defproxy.monitor_uri);
2810 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002811 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002812 free(defproxy.fwdfor_hdr_name);
2813 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002814 free(defproxy.orgto_hdr_name);
2815 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002816 free(defproxy.server_id_hdr_name);
2817 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002818 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002819 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002820 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002821 free(defproxy.expect_regex);
2822 defproxy.expect_regex = NULL;
2823 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002824
Willy Tarreau62a61232013-04-12 18:13:46 +02002825 if (defproxy.conf.logformat_string != default_http_log_format &&
2826 defproxy.conf.logformat_string != default_tcp_log_format &&
2827 defproxy.conf.logformat_string != clf_http_log_format)
2828 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002829
Willy Tarreau62a61232013-04-12 18:13:46 +02002830 free(defproxy.conf.uniqueid_format_string);
2831 free(defproxy.conf.lfs_file);
2832 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002833 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002834 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002835
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002836 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2837 free(defproxy.conf.logformat_sd_string);
2838 free(defproxy.conf.lfsd_file);
2839
Willy Tarreaua534fea2008-08-03 12:19:50 +02002840 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002841 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002842
Willy Tarreaubaaee002006-06-26 02:48:02 +02002843 /* we cannot free uri_auth because it might already be used */
2844 init_default_instance();
2845 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002846 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2847 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002848 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 }
2851 else if (curproxy == NULL) {
2852 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002856
2857 /* update the current file and line being parsed */
2858 curproxy->conf.args.file = curproxy->conf.file;
2859 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002860
2861 /* Now let's parse the proxy-specific keywords */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002862 if (!strcmp(args[0], "server") ||
2863 !strcmp(args[0], "default-server") ||
2864 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002865 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2866 if (err_code & ERR_FATAL)
2867 goto out;
2868 }
2869 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002870 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002871 int cur_arg;
2872
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 if (curproxy == &defproxy) {
2874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002878 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880
Willy Tarreau24709282013-03-10 21:32:12 +01002881 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002882 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002887
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002888 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002889
2890 /* use default settings for unix sockets */
2891 bind_conf->ux.uid = global.unix_bind.ux.uid;
2892 bind_conf->ux.gid = global.unix_bind.ux.gid;
2893 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002894
2895 /* NOTE: the following line might create several listeners if there
2896 * are comma-separated IPs or port ranges. So all further processing
2897 * will have to be applied to all listeners created after last_listen.
2898 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002899 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2900 if (errmsg && *errmsg) {
2901 indent_msg(&errmsg, 2);
2902 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002903 }
2904 else
2905 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2906 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
2909 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002910
Willy Tarreau4348fad2012-09-20 16:48:07 +02002911 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2912 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002913 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002914 }
2915
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002916 cur_arg = 2;
2917 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002918 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002919 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002920 char *err;
2921
Willy Tarreau26982662012-09-12 23:17:10 +02002922 kw = bind_find_kw(args[cur_arg]);
2923 if (kw) {
2924 char *err = NULL;
2925 int code;
2926
2927 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002928 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2929 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002930 cur_arg += 1 + kw->skip ;
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933 }
2934
Willy Tarreau4348fad2012-09-20 16:48:07 +02002935 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002936 err_code |= code;
2937
2938 if (code) {
2939 if (err && *err) {
2940 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002941 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002942 }
2943 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002944 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2945 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002946 if (code & ERR_FATAL) {
2947 free(err);
2948 cur_arg += 1 + kw->skip;
2949 goto out;
2950 }
2951 }
2952 free(err);
2953 cur_arg += 1 + kw->skip;
2954 continue;
2955 }
2956
Willy Tarreau8638f482012-09-18 18:01:17 +02002957 err = NULL;
2958 if (!bind_dumped) {
2959 bind_dump_kws(&err);
2960 indent_msg(&err, 4);
2961 bind_dumped = 1;
2962 }
2963
2964 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2965 file, linenum, args[0], args[1], args[cur_arg],
2966 err ? " Registered keywords :" : "", err ? err : "");
2967 free(err);
2968
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002971 }
Willy Tarreau93893792009-07-23 13:19:11 +02002972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 }
2974 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002975 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2977 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002981 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002983
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 /* flush useless bits */
2985 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002988 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002989 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002991
William Lallemanddf1425a2015-04-28 20:17:49 +02002992 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2993 goto out;
2994
Willy Tarreau1c47f852006-07-09 08:22:27 +02002995 if (!*args[1]) {
2996 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2997 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003000 }
3001
Willy Tarreaua534fea2008-08-03 12:19:50 +02003002 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003003 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003004 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003005 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003006 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3007
Willy Tarreau93893792009-07-23 13:19:11 +02003008 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003011 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3012 goto out;
3013
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3015 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3016 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3017 else {
3018 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 }
3022 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003023 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003024 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003025
3026 if (curproxy == &defproxy) {
3027 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3028 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003031 }
3032
William Lallemanddf1425a2015-04-28 20:17:49 +02003033 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3034 goto out;
3035
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003036 if (!*args[1]) {
3037 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003041 }
3042
3043 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003044 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003045 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003046
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003047 if (curproxy->uuid <= 0) {
3048 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003049 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003052 }
3053
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003054 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3055 if (node) {
3056 struct proxy *target = container_of(node, struct proxy, conf.id);
3057 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3058 file, linenum, proxy_type_str(curproxy), curproxy->id,
3059 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003064 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003065 else if (!strcmp(args[0], "description")) {
3066 int i, len=0;
3067 char *d;
3068
Cyril Bonté99ed3272010-01-24 23:29:44 +01003069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3071 file, linenum, args[0]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003076 if (!*args[1]) {
3077 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3078 file, linenum, args[0]);
3079 return -1;
3080 }
3081
Willy Tarreau348acfe2014-04-14 15:00:39 +02003082 for (i = 1; *args[i]; i++)
3083 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003084
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003085 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003086 curproxy->desc = d;
3087
Willy Tarreau348acfe2014-04-14 15:00:39 +02003088 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3089 for (i = 2; *args[i]; i++)
3090 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003091
3092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003094 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 curproxy->state = PR_STSTOPPED;
3097 }
3098 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003099 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 curproxy->state = PR_STNEW;
3102 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003103 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3104 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003105 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003106
3107 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003108 unsigned int low, high;
3109
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003110 if (strcmp(args[cur_arg], "all") == 0) {
3111 set = 0;
3112 break;
3113 }
3114 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003115 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003116 }
3117 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003118 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003119 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003120 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003121 char *dash = strchr(args[cur_arg], '-');
3122
3123 low = high = str2uic(args[cur_arg]);
3124 if (dash)
3125 high = str2uic(dash + 1);
3126
3127 if (high < low) {
3128 unsigned int swap = low;
3129 low = high;
3130 high = swap;
3131 }
3132
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003133 if (low < 1 || high > LONGBITS) {
3134 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3135 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003138 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003139 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003140 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003141 }
3142 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003143 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3144 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003147 }
3148 cur_arg++;
3149 }
3150 curproxy->bind_proc = set;
3151 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003152 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003153 if (curproxy == &defproxy) {
3154 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003157 }
3158
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003159 err = invalid_char(args[1]);
3160 if (err) {
3161 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3162 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003164 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003165 }
3166
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003167 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003168 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3169 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003172 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003173 }
3174 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3175
3176 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3177 err_code |= ERR_WARN;
3178
3179 if (*(args[1]) == 0) {
3180 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3181 file, linenum, args[0]);
3182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
3184 }
3185 free(curproxy->dyncookie_key);
3186 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3189 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190
Willy Tarreau977b8e42006-12-29 14:19:17 +01003191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003193
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 if (*(args[1]) == 0) {
3195 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003200
Willy Tarreau67402132012-05-31 20:40:20 +02003201 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003202 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003203 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003204 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 curproxy->cookie_name = strdup(args[1]);
3206 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003207
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 cur_arg = 2;
3209 while (*(args[cur_arg])) {
3210 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003211 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 }
3213 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003214 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
3216 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003217 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
3219 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003220 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 }
3222 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003223 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003225 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003226 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003229 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003231 else if (!strcmp(args[cur_arg], "httponly")) {
3232 curproxy->ck_opts |= PR_CK_HTTPONLY;
3233 }
3234 else if (!strcmp(args[cur_arg], "secure")) {
3235 curproxy->ck_opts |= PR_CK_SECURE;
3236 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003237 else if (!strcmp(args[cur_arg], "domain")) {
3238 if (!*args[cur_arg + 1]) {
3239 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3240 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003243 }
3244
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003245 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003246 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003247 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3248 " dots nor does not start with a dot."
3249 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003250 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003251 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003252 }
3253
3254 err = invalid_domainchar(args[cur_arg + 1]);
3255 if (err) {
3256 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3257 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003260 }
3261
Willy Tarreau68a897b2009-12-03 23:28:34 +01003262 if (!curproxy->cookie_domain) {
3263 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3264 } else {
3265 /* one domain was already specified, add another one by
3266 * building the string which will be returned along with
3267 * the cookie.
3268 */
3269 char *new_ptr;
3270 int new_len = strlen(curproxy->cookie_domain) +
3271 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3272 new_ptr = malloc(new_len);
3273 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3274 free(curproxy->cookie_domain);
3275 curproxy->cookie_domain = new_ptr;
3276 }
Willy Tarreau31936852010-10-06 16:59:56 +02003277 cur_arg++;
3278 }
3279 else if (!strcmp(args[cur_arg], "maxidle")) {
3280 unsigned int maxidle;
3281 const char *res;
3282
3283 if (!*args[cur_arg + 1]) {
3284 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3285 file, linenum, args[cur_arg]);
3286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
3288 }
3289
3290 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3291 if (res) {
3292 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3293 file, linenum, *res, args[cur_arg]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297 curproxy->cookie_maxidle = maxidle;
3298 cur_arg++;
3299 }
3300 else if (!strcmp(args[cur_arg], "maxlife")) {
3301 unsigned int maxlife;
3302 const char *res;
3303
3304 if (!*args[cur_arg + 1]) {
3305 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3306 file, linenum, args[cur_arg]);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
3310
3311 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3312 if (res) {
3313 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3314 file, linenum, *res, args[cur_arg]);
3315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
3317 }
3318 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003319 cur_arg++;
3320 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003321 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003322
3323 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3324 err_code |= ERR_WARN;
3325 curproxy->ck_opts |= PR_CK_DYNAMIC;
3326 }
3327
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003329 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 +02003330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
3334 cur_arg++;
3335 }
Willy Tarreau67402132012-05-31 20:40:20 +02003336 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3338 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
3341
Willy Tarreau67402132012-05-31 20:40:20 +02003342 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3344 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003347
Willy Tarreau67402132012-05-31 20:40:20 +02003348 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003349 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3350 file, linenum);
3351 err_code |= ERR_ALERT | ERR_FATAL;
3352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003354 else if (!strcmp(args[0], "email-alert")) {
3355 if (*(args[1]) == 0) {
3356 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3357 file, linenum, args[0]);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
3361
3362 if (!strcmp(args[1], "from")) {
3363 if (*(args[1]) == 0) {
3364 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3365 file, linenum, args[1]);
3366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
3368 }
3369 free(curproxy->email_alert.from);
3370 curproxy->email_alert.from = strdup(args[2]);
3371 }
3372 else if (!strcmp(args[1], "mailers")) {
3373 if (*(args[1]) == 0) {
3374 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3375 file, linenum, args[1]);
3376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
3378 }
3379 free(curproxy->email_alert.mailers.name);
3380 curproxy->email_alert.mailers.name = strdup(args[2]);
3381 }
3382 else if (!strcmp(args[1], "myhostname")) {
3383 if (*(args[1]) == 0) {
3384 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3385 file, linenum, args[1]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389 free(curproxy->email_alert.myhostname);
3390 curproxy->email_alert.myhostname = strdup(args[2]);
3391 }
Simon Horman64e34162015-02-06 11:11:57 +09003392 else if (!strcmp(args[1], "level")) {
3393 curproxy->email_alert.level = get_log_level(args[2]);
3394 if (curproxy->email_alert.level < 0) {
3395 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3396 file, linenum, args[1], args[2]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400 }
Simon Horman9dc49962015-01-30 11:22:59 +09003401 else if (!strcmp(args[1], "to")) {
3402 if (*(args[1]) == 0) {
3403 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3404 file, linenum, args[1]);
3405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408 free(curproxy->email_alert.to);
3409 curproxy->email_alert.to = strdup(args[2]);
3410 }
3411 else {
3412 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3413 file, linenum, args[1]);
3414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
3416 }
Simon Horman64e34162015-02-06 11:11:57 +09003417 /* Indicate that the email_alert is at least partially configured */
3418 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003419 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003420 else if (!strcmp(args[0], "external-check")) {
3421 if (*(args[1]) == 0) {
3422 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3423 file, linenum, args[0]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427
3428 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003429 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003430 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003431 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003432 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3433 file, linenum, args[1]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437 free(curproxy->check_command);
3438 curproxy->check_command = strdup(args[2]);
3439 }
3440 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003441 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003442 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003443 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003444 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3445 file, linenum, args[1]);
3446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
3448 }
3449 free(curproxy->check_path);
3450 curproxy->check_path = strdup(args[2]);
3451 }
3452 else {
3453 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3454 file, linenum, args[1]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
3458 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003459 else if (!strcmp(args[0], "persist")) { /* persist */
3460 if (*(args[1]) == 0) {
3461 Alert("parsing [%s:%d] : missing persist method.\n",
3462 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003465 }
3466
3467 if (!strncmp(args[1], "rdp-cookie", 10)) {
3468 curproxy->options2 |= PR_O2_RDPC_PRST;
3469
Emeric Brunb982a3d2010-01-04 15:45:53 +01003470 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003471 const char *beg, *end;
3472
3473 beg = args[1] + 11;
3474 end = strchr(beg, ')');
3475
William Lallemanddf1425a2015-04-28 20:17:49 +02003476 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3477 goto out;
3478
Emeric Brun647caf12009-06-30 17:57:00 +02003479 if (!end || end == beg) {
3480 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3481 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003484 }
3485
3486 free(curproxy->rdp_cookie_name);
3487 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3488 curproxy->rdp_cookie_len = end-beg;
3489 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003490 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003491 free(curproxy->rdp_cookie_name);
3492 curproxy->rdp_cookie_name = strdup("msts");
3493 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3494 }
3495 else { /* syntax */
3496 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3497 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003500 }
3501 }
3502 else {
3503 Alert("parsing [%s:%d] : unknown persist method.\n",
3504 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003507 }
3508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003510 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003514 else if (!strcmp(args[0], "load-server-state-from-file")) {
3515 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3516 err_code |= ERR_WARN;
3517 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3518 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3519 }
3520 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3521 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3522 }
3523 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3524 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3525 }
3526 else {
3527 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3528 file, linenum, args[0], args[1]);
3529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
3531 }
3532 }
3533 else if (!strcmp(args[0], "server-state-file-name")) {
3534 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3535 err_code |= ERR_WARN;
3536 if (*(args[1]) == 0) {
3537 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3538 file, linenum, args[0]);
3539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
3541 }
3542 else if (!strcmp(args[1], "use-backend-name"))
3543 curproxy->server_state_file_name = strdup(curproxy->id);
3544 else
3545 curproxy->server_state_file_name = strdup(args[1]);
3546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003548 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003550
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003552 if (curproxy == &defproxy) {
3553 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
3556 }
3557
William Lallemand1a748ae2015-05-19 16:37:23 +02003558 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3559 goto out;
3560
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 if (*(args[4]) == 0) {
3562 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3563 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003567 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568 curproxy->capture_name = strdup(args[2]);
3569 curproxy->capture_namelen = strlen(curproxy->capture_name);
3570 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 curproxy->to_log |= LW_COOKIE;
3572 }
3573 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3574 struct cap_hdr *hdr;
3575
3576 if (curproxy == &defproxy) {
3577 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 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
3581
William Lallemand1a748ae2015-05-19 16:37:23 +02003582 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3583 goto out;
3584
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3586 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3587 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 }
3591
Vincent Bernat02779b62016-04-03 13:48:43 +02003592 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 hdr->next = curproxy->req_cap;
3594 hdr->name = strdup(args[3]);
3595 hdr->namelen = strlen(args[3]);
3596 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003597 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 hdr->index = curproxy->nb_req_cap++;
3599 curproxy->req_cap = hdr;
3600 curproxy->to_log |= LW_REQHDR;
3601 }
3602 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3603 struct cap_hdr *hdr;
3604
3605 if (curproxy == &defproxy) {
3606 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 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
3610
William Lallemand1a748ae2015-05-19 16:37:23 +02003611 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3612 goto out;
3613
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3615 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3616 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003620 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 hdr->next = curproxy->rsp_cap;
3622 hdr->name = strdup(args[3]);
3623 hdr->namelen = strlen(args[3]);
3624 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003625 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 hdr->index = curproxy->nb_rsp_cap++;
3627 curproxy->rsp_cap = hdr;
3628 curproxy->to_log |= LW_RSPHDR;
3629 }
3630 else {
3631 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3632 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 }
3636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003640
William Lallemanddf1425a2015-04-28 20:17:49 +02003641 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3642 goto out;
3643
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 if (*(args[1]) == 0) {
3645 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3646 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650 curproxy->conn_retries = atol(args[1]);
3651 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003652 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003653 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003654
3655 if (curproxy == &defproxy) {
3656 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
3659 }
3660
Willy Tarreau20b0de52012-12-24 15:45:22 +01003661 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003662 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003663 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3664 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3665 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3666 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003667 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 +01003668 file, linenum, args[0]);
3669 err_code |= ERR_WARN;
3670 }
3671
Willy Tarreauff011f22011-01-06 17:51:27 +01003672 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003673
Willy Tarreauff011f22011-01-06 17:51:27 +01003674 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003675 err_code |= ERR_ALERT | ERR_ABORT;
3676 goto out;
3677 }
3678
Willy Tarreau5002f572014-04-23 01:32:02 +02003679 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003680 err_code |= warnif_cond_conflicts(rule->cond,
3681 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3682 file, linenum);
3683
Willy Tarreauff011f22011-01-06 17:51:27 +01003684 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003685 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003686 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003687 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003688
3689 if (curproxy == &defproxy) {
3690 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
3693 }
3694
3695 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003696 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003697 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3698 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003699 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3700 file, linenum, args[0]);
3701 err_code |= ERR_WARN;
3702 }
3703
3704 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3705
3706 if (!rule) {
3707 err_code |= ERR_ALERT | ERR_ABORT;
3708 goto out;
3709 }
3710
3711 err_code |= warnif_cond_conflicts(rule->cond,
3712 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3713 file, linenum);
3714
3715 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3716 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003717 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3718 /* set the header name and length into the proxy structure */
3719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3720 err_code |= ERR_WARN;
3721
3722 if (!*args[1]) {
3723 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3724 file, linenum, args[0]);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
3728
3729 /* set the desired header name */
3730 free(curproxy->server_id_hdr_name);
3731 curproxy->server_id_hdr_name = strdup(args[1]);
3732 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3733 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003734 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003735 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003736
Willy Tarreaub099aca2008-10-12 17:26:37 +02003737 if (curproxy == &defproxy) {
3738 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003741 }
3742
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003743 /* emulate "block" using "http-request block". Since these rules are supposed to
3744 * be processed before all http-request rules, we put them into their own list
3745 * and will insert them at the end.
3746 */
3747 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3748 if (!rule) {
3749 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003750 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003751 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003752 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3753 err_code |= warnif_cond_conflicts(rule->cond,
3754 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3755 file, linenum);
3756 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003757
3758 if (!already_warned(WARN_BLOCK_DEPRECATED))
3759 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]);
3760
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003761 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003762 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003763 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003764
Cyril Bonté99ed3272010-01-24 23:29:44 +01003765 if (curproxy == &defproxy) {
3766 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
3769 }
3770
Willy Tarreaube4653b2015-05-28 15:26:58 +02003771 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003772 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3773 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003776 }
3777
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003778 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003779 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003780 err_code |= warnif_cond_conflicts(rule->cond,
3781 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3782 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003783 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003784 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003785 struct switching_rule *rule;
3786
Willy Tarreaub099aca2008-10-12 17:26:37 +02003787 if (curproxy == &defproxy) {
3788 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003791 }
3792
Willy Tarreau55ea7572007-06-17 19:56:27 +02003793 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003795
3796 if (*(args[1]) == 0) {
3797 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003800 }
3801
Willy Tarreauf51658d2014-04-23 01:21:56 +02003802 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3803 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3804 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3805 file, linenum, errmsg);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003809
Willy Tarreauf51658d2014-04-23 01:21:56 +02003810 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003811 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003812 else if (*args[2]) {
3813 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3814 file, linenum, args[2]);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
3817 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003818
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003819 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003820 if (!rule) {
3821 Alert("Out of memory error.\n");
3822 goto out;
3823 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003824 rule->cond = cond;
3825 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003826 rule->line = linenum;
3827 rule->file = strdup(file);
3828 if (!rule->file) {
3829 Alert("Out of memory error.\n");
3830 goto out;
3831 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003832 LIST_INIT(&rule->list);
3833 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3834 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003835 else if (strcmp(args[0], "use-server") == 0) {
3836 struct server_rule *rule;
3837
3838 if (curproxy == &defproxy) {
3839 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843
3844 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3845 err_code |= ERR_WARN;
3846
3847 if (*(args[1]) == 0) {
3848 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852
3853 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3854 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3855 file, linenum, args[0]);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003860 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3861 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3862 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003867 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003868
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003869 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003870 rule->cond = cond;
3871 rule->srv.name = strdup(args[1]);
3872 LIST_INIT(&rule->list);
3873 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3874 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3875 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003876 else if ((!strcmp(args[0], "force-persist")) ||
3877 (!strcmp(args[0], "ignore-persist"))) {
3878 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003879
3880 if (curproxy == &defproxy) {
3881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
3885
3886 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3887 err_code |= ERR_WARN;
3888
Willy Tarreauef6494c2010-01-28 17:12:36 +01003889 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003890 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3891 file, linenum, args[0]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003896 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3897 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3898 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
3901 }
3902
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003903 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3904 * where force-persist is applied.
3905 */
3906 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003907
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003908 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003909 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003910 if (!strcmp(args[0], "force-persist")) {
3911 rule->type = PERSIST_TYPE_FORCE;
3912 } else {
3913 rule->type = PERSIST_TYPE_IGNORE;
3914 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003915 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003916 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003917 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003918 else if (!strcmp(args[0], "stick-table")) {
3919 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003920 struct proxy *other;
3921
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003922 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003923 if (other) {
3924 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3925 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003929
Emeric Brun32da3c42010-09-23 18:39:19 +02003930 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003931 curproxy->table.type = (unsigned int)-1;
3932 while (*args[myidx]) {
3933 const char *err;
3934
3935 if (strcmp(args[myidx], "size") == 0) {
3936 myidx++;
3937 if (!*(args[myidx])) {
3938 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3939 file, linenum, args[myidx-1]);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
3943 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3944 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3945 file, linenum, *err, args[myidx-1]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003949 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003950 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003951 else if (strcmp(args[myidx], "peers") == 0) {
3952 myidx++;
Godbach50523162013-12-11 19:48:57 +08003953 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003954 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3955 file, linenum, args[myidx-1]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Godbach50523162013-12-11 19:48:57 +08003958 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003959 curproxy->table.peers.name = strdup(args[myidx++]);
3960 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003961 else if (strcmp(args[myidx], "expire") == 0) {
3962 myidx++;
3963 if (!*(args[myidx])) {
3964 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3965 file, linenum, args[myidx-1]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3970 if (err) {
3971 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3972 file, linenum, *err, args[myidx-1]);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003976 if (val > INT_MAX) {
3977 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3978 file, linenum, val);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003982 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003983 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003984 }
3985 else if (strcmp(args[myidx], "nopurge") == 0) {
3986 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003987 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003988 }
3989 else if (strcmp(args[myidx], "type") == 0) {
3990 myidx++;
3991 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3992 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3993 file, linenum, args[myidx]);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
3996 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003997 /* myidx already points to next arg */
3998 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003999 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004000 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004001 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004002
4003 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004004 nw = args[myidx];
4005 while (*nw) {
4006 /* the "store" keyword supports a comma-separated list */
4007 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004008 sa = NULL; /* store arg */
4009 while (*nw && *nw != ',') {
4010 if (*nw == '(') {
4011 *nw = 0;
4012 sa = ++nw;
4013 while (*nw != ')') {
4014 if (!*nw) {
4015 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4016 file, linenum, args[0], cw);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020 nw++;
4021 }
4022 *nw = '\0';
4023 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004024 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004025 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004026 if (*nw)
4027 *nw++ = '\0';
4028 type = stktable_get_data_type(cw);
4029 if (type < 0) {
4030 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4031 file, linenum, args[0], cw);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
Willy Tarreauac782882010-06-20 10:41:54 +02004035
4036 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4037 switch (err) {
4038 case PE_NONE: break;
4039 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004040 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4041 file, linenum, args[0], cw);
4042 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004043 break;
4044
4045 case PE_ARG_MISSING:
4046 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4047 file, linenum, args[0], cw);
4048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
4050
4051 case PE_ARG_NOT_USED:
4052 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4053 file, linenum, args[0], cw);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
4056
4057 default:
4058 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4059 file, linenum, args[0], cw);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004062 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004063 }
4064 myidx++;
4065 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004066 else {
4067 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4068 file, linenum, args[myidx]);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004071 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004072 }
4073
4074 if (!curproxy->table.size) {
4075 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4076 file, linenum);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080
4081 if (curproxy->table.type == (unsigned int)-1) {
4082 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4083 file, linenum);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087 }
4088 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004089 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004090 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004091 int myidx = 0;
4092 const char *name = NULL;
4093 int flags;
4094
4095 if (curproxy == &defproxy) {
4096 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
4100
4101 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4102 err_code |= ERR_WARN;
4103 goto out;
4104 }
4105
4106 myidx++;
4107 if ((strcmp(args[myidx], "store") == 0) ||
4108 (strcmp(args[myidx], "store-request") == 0)) {
4109 myidx++;
4110 flags = STK_IS_STORE;
4111 }
4112 else if (strcmp(args[myidx], "store-response") == 0) {
4113 myidx++;
4114 flags = STK_IS_STORE | STK_ON_RSP;
4115 }
4116 else if (strcmp(args[myidx], "match") == 0) {
4117 myidx++;
4118 flags = STK_IS_MATCH;
4119 }
4120 else if (strcmp(args[myidx], "on") == 0) {
4121 myidx++;
4122 flags = STK_IS_MATCH | STK_IS_STORE;
4123 }
4124 else {
4125 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129
4130 if (*(args[myidx]) == 0) {
4131 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
4135
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004136 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004137 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004138 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004139 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143
4144 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004145 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4146 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\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 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004153 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4154 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4155 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004157 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 goto out;
4159 }
4160 }
4161
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004162 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004163 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004164
Emeric Brunb982a3d2010-01-04 15:45:53 +01004165 if (strcmp(args[myidx], "table") == 0) {
4166 myidx++;
4167 name = args[myidx++];
4168 }
4169
Willy Tarreauef6494c2010-01-28 17:12:36 +01004170 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004171 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4172 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4173 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004174 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004175 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004176 goto out;
4177 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004178 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004179 else if (*(args[myidx])) {
4180 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4181 file, linenum, args[0], args[myidx]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004183 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004184 goto out;
4185 }
Emeric Brun97679e72010-09-23 17:56:44 +02004186 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004187 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004188 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004189 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004190
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004191 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004192 rule->cond = cond;
4193 rule->expr = expr;
4194 rule->flags = flags;
4195 rule->table.name = name ? strdup(name) : NULL;
4196 LIST_INIT(&rule->list);
4197 if (flags & STK_ON_RSP)
4198 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4199 else
4200 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 else if (!strcmp(args[0], "stats")) {
4203 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4204 curproxy->uri_auth = NULL; /* we must detach from the default config */
4205
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004206 if (!*args[1]) {
4207 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004208 } else if (!strcmp(args[1], "admin")) {
4209 struct stats_admin_rule *rule;
4210
4211 if (curproxy == &defproxy) {
4212 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
4215 }
4216
4217 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4218 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4219 err_code |= ERR_ALERT | ERR_ABORT;
4220 goto out;
4221 }
4222
4223 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4224 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4225 file, linenum, args[0], args[1]);
4226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
4228 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004229 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4230 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4231 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004236 err_code |= warnif_cond_conflicts(cond,
4237 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4238 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004239
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004240 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004241 rule->cond = cond;
4242 LIST_INIT(&rule->list);
4243 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 } else if (!strcmp(args[1], "uri")) {
4245 if (*(args[2]) == 0) {
4246 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004249 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_ABORT;
4252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 }
4254 } else if (!strcmp(args[1], "realm")) {
4255 if (*(args[2]) == 0) {
4256 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4260 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004261 err_code |= ERR_ALERT | ERR_ABORT;
4262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004264 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004265 unsigned interval;
4266
4267 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4268 if (err) {
4269 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4270 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004273 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_ABORT;
4276 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004277 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004278 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004279 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004280
4281 if (curproxy == &defproxy) {
4282 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 }
4286
4287 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4288 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4289 err_code |= ERR_ALERT | ERR_ABORT;
4290 goto out;
4291 }
4292
Willy Tarreauff011f22011-01-06 17:51:27 +01004293 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004294 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004295 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4296 file, linenum, args[0]);
4297 err_code |= ERR_WARN;
4298 }
4299
Willy Tarreauff011f22011-01-06 17:51:27 +01004300 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004301
Willy Tarreauff011f22011-01-06 17:51:27 +01004302 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004303 err_code |= ERR_ALERT | ERR_ABORT;
4304 goto out;
4305 }
4306
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004307 err_code |= warnif_cond_conflicts(rule->cond,
4308 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4309 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004310 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004311
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 } else if (!strcmp(args[1], "auth")) {
4313 if (*(args[2]) == 0) {
4314 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4318 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_ABORT;
4320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004321 }
4322 } else if (!strcmp(args[1], "scope")) {
4323 if (*(args[2]) == 0) {
4324 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4328 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004329 err_code |= ERR_ALERT | ERR_ABORT;
4330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 }
4332 } else if (!strcmp(args[1], "enable")) {
4333 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4334 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004335 err_code |= ERR_ALERT | ERR_ABORT;
4336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004338 } else if (!strcmp(args[1], "hide-version")) {
4339 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4340 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004341 err_code |= ERR_ALERT | ERR_ABORT;
4342 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004343 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004344 } else if (!strcmp(args[1], "show-legends")) {
4345 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4346 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4347 err_code |= ERR_ALERT | ERR_ABORT;
4348 goto out;
4349 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004350 } else if (!strcmp(args[1], "show-node")) {
4351
4352 if (*args[2]) {
4353 int i;
4354 char c;
4355
4356 for (i=0; args[2][i]; i++) {
4357 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004358 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4359 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004360 break;
4361 }
4362
4363 if (!i || args[2][i]) {
4364 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4365 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4366 file, linenum, args[0], args[1]);
4367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370 }
4371
4372 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4373 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4374 err_code |= ERR_ALERT | ERR_ABORT;
4375 goto out;
4376 }
4377 } else if (!strcmp(args[1], "show-desc")) {
4378 char *desc = NULL;
4379
4380 if (*args[2]) {
4381 int i, len=0;
4382 char *d;
4383
Willy Tarreau348acfe2014-04-14 15:00:39 +02004384 for (i = 2; *args[i]; i++)
4385 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004386
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004387 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004388
Willy Tarreau348acfe2014-04-14 15:00:39 +02004389 d += snprintf(d, desc + len - d, "%s", args[2]);
4390 for (i = 3; *args[i]; i++)
4391 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004392 }
4393
4394 if (!*args[2] && !global.desc)
4395 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4396 file, linenum, args[1]);
4397 else {
4398 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4399 free(desc);
4400 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4401 err_code |= ERR_ALERT | ERR_ABORT;
4402 goto out;
4403 }
4404 free(desc);
4405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004406 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004407stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004408 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 +01004409 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 }
4413 }
4414 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004415 int optnum;
4416
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004417 if (*(args[1]) == '\0') {
4418 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004423
4424 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4425 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004426 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4427 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4428 file, linenum, cfg_opts[optnum].name);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004432 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4433 goto out;
4434
Willy Tarreau93893792009-07-23 13:19:11 +02004435 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4436 err_code |= ERR_WARN;
4437 goto out;
4438 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004439
Willy Tarreau3842f002009-06-14 11:39:52 +02004440 curproxy->no_options &= ~cfg_opts[optnum].val;
4441 curproxy->options &= ~cfg_opts[optnum].val;
4442
4443 switch (kwm) {
4444 case KWM_STD:
4445 curproxy->options |= cfg_opts[optnum].val;
4446 break;
4447 case KWM_NO:
4448 curproxy->no_options |= cfg_opts[optnum].val;
4449 break;
4450 case KWM_DEF: /* already cleared */
4451 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004452 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004453
Willy Tarreau93893792009-07-23 13:19:11 +02004454 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004455 }
4456 }
4457
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004458 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4459 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004460 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4461 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4462 file, linenum, cfg_opts2[optnum].name);
4463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
4465 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004466 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4467 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004468 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4469 err_code |= ERR_WARN;
4470 goto out;
4471 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004472
Willy Tarreau3842f002009-06-14 11:39:52 +02004473 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4474 curproxy->options2 &= ~cfg_opts2[optnum].val;
4475
4476 switch (kwm) {
4477 case KWM_STD:
4478 curproxy->options2 |= cfg_opts2[optnum].val;
4479 break;
4480 case KWM_NO:
4481 curproxy->no_options2 |= cfg_opts2[optnum].val;
4482 break;
4483 case KWM_DEF: /* already cleared */
4484 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004485 }
Willy Tarreau93893792009-07-23 13:19:11 +02004486 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004487 }
4488 }
4489
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004490 /* HTTP options override each other. They can be cancelled using
4491 * "no option xxx" which only switches to default mode if the mode
4492 * was this one (useful for cancelling options set in defaults
4493 * sections).
4494 */
4495 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004496 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4497 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004498 if (kwm == KWM_STD) {
4499 curproxy->options &= ~PR_O_HTTP_MODE;
4500 curproxy->options |= PR_O_HTTP_PCL;
4501 goto out;
4502 }
4503 else if (kwm == KWM_NO) {
4504 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4505 curproxy->options &= ~PR_O_HTTP_MODE;
4506 goto out;
4507 }
4508 }
4509 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004510 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4511 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004512 if (kwm == KWM_STD) {
4513 curproxy->options &= ~PR_O_HTTP_MODE;
4514 curproxy->options |= PR_O_HTTP_FCL;
4515 goto out;
4516 }
4517 else if (kwm == KWM_NO) {
4518 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4519 curproxy->options &= ~PR_O_HTTP_MODE;
4520 goto out;
4521 }
4522 }
4523 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004524 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4525 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004526 if (kwm == KWM_STD) {
4527 curproxy->options &= ~PR_O_HTTP_MODE;
4528 curproxy->options |= PR_O_HTTP_SCL;
4529 goto out;
4530 }
4531 else if (kwm == KWM_NO) {
4532 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4533 curproxy->options &= ~PR_O_HTTP_MODE;
4534 goto out;
4535 }
4536 }
4537 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004538 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4539 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004540 if (kwm == KWM_STD) {
4541 curproxy->options &= ~PR_O_HTTP_MODE;
4542 curproxy->options |= PR_O_HTTP_KAL;
4543 goto out;
4544 }
4545 else if (kwm == KWM_NO) {
4546 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4547 curproxy->options &= ~PR_O_HTTP_MODE;
4548 goto out;
4549 }
4550 }
4551 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004552 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4553 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004554 if (kwm == KWM_STD) {
4555 curproxy->options &= ~PR_O_HTTP_MODE;
4556 curproxy->options |= PR_O_HTTP_TUN;
4557 goto out;
4558 }
4559 else if (kwm == KWM_NO) {
4560 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4561 curproxy->options &= ~PR_O_HTTP_MODE;
4562 goto out;
4563 }
4564 }
4565
Joseph Lynch726ab712015-05-11 23:25:34 -07004566 /* Redispatch can take an integer argument that control when the
4567 * resispatch occurs. All values are relative to the retries option.
4568 * This can be cancelled using "no option xxx".
4569 */
4570 if (strcmp(args[1], "redispatch") == 0) {
4571 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4572 err_code |= ERR_WARN;
4573 goto out;
4574 }
4575
4576 curproxy->no_options &= ~PR_O_REDISP;
4577 curproxy->options &= ~PR_O_REDISP;
4578
4579 switch (kwm) {
4580 case KWM_STD:
4581 curproxy->options |= PR_O_REDISP;
4582 curproxy->redispatch_after = -1;
4583 if(*args[2]) {
4584 curproxy->redispatch_after = atol(args[2]);
4585 }
4586 break;
4587 case KWM_NO:
4588 curproxy->no_options |= PR_O_REDISP;
4589 curproxy->redispatch_after = 0;
4590 break;
4591 case KWM_DEF: /* already cleared */
4592 break;
4593 }
4594 goto out;
4595 }
4596
Willy Tarreau3842f002009-06-14 11:39:52 +02004597 if (kwm != KWM_STD) {
4598 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004599 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004602 }
4603
Emeric Brun3a058f32009-06-30 18:26:00 +02004604 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004605 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004607 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004608 if (*(args[2]) != '\0') {
4609 if (!strcmp(args[2], "clf")) {
4610 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004611 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004612 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004613 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004616 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004617 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4618 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004619 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004620 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4621 char *oldlogformat = "log-format";
4622 char *clflogformat = "";
4623
4624 if (curproxy->conf.logformat_string == default_http_log_format)
4625 oldlogformat = "option httplog";
4626 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4627 oldlogformat = "option tcplog";
4628 else if (curproxy->conf.logformat_string == clf_http_log_format)
4629 oldlogformat = "option httplog clf";
4630 if (logformat == clf_http_log_format)
4631 clflogformat = " clf";
4632 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4633 file, linenum, clflogformat, oldlogformat);
4634 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004635 if (curproxy->conf.logformat_string != default_http_log_format &&
4636 curproxy->conf.logformat_string != default_tcp_log_format &&
4637 curproxy->conf.logformat_string != clf_http_log_format)
4638 free(curproxy->conf.logformat_string);
4639 curproxy->conf.logformat_string = logformat;
4640
4641 free(curproxy->conf.lfs_file);
4642 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4643 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004644 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004645 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004646 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4647 char *oldlogformat = "log-format";
4648
4649 if (curproxy->conf.logformat_string == default_http_log_format)
4650 oldlogformat = "option httplog";
4651 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4652 oldlogformat = "option tcplog";
4653 else if (curproxy->conf.logformat_string == clf_http_log_format)
4654 oldlogformat = "option httplog clf";
4655 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4656 file, linenum, oldlogformat);
4657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004659 if (curproxy->conf.logformat_string != default_http_log_format &&
4660 curproxy->conf.logformat_string != default_tcp_log_format &&
4661 curproxy->conf.logformat_string != clf_http_log_format)
4662 free(curproxy->conf.logformat_string);
4663 curproxy->conf.logformat_string = default_tcp_log_format;
4664
4665 free(curproxy->conf.lfs_file);
4666 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4667 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004668
4669 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4670 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004673 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004674 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004675 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004676
William Lallemanddf1425a2015-04-28 20:17:49 +02004677 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4678 goto out;
4679
Willy Tarreau13943ab2006-12-31 00:24:10 +01004680 if (curproxy->cap & PR_CAP_FE)
4681 curproxy->options |= PR_O_TCP_CLI_KA;
4682 if (curproxy->cap & PR_CAP_BE)
4683 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 }
4685 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004686 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004687 err_code |= ERR_WARN;
4688
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004690 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004691 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004692 curproxy->options2 &= ~PR_O2_CHK_ANY;
4693 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 if (!*args[2]) { /* no argument */
4695 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4696 curproxy->check_len = strlen(DEF_CHECK_REQ);
4697 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004698 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004699 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004701 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004703 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 if (*args[4])
4705 reqlen += strlen(args[4]);
4706 else
4707 reqlen += strlen("HTTP/1.0");
4708
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004709 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004711 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004713 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4714 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004715 }
4716 else if (!strcmp(args[1], "ssl-hello-chk")) {
4717 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004718 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004719 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004720
Willy Tarreaua534fea2008-08-03 12:19:50 +02004721 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004722 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004723 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004724 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004725
4726 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 }
Willy Tarreau23677902007-05-08 23:50:35 +02004729 else if (!strcmp(args[1], "smtpchk")) {
4730 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004731 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004732 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004733 curproxy->options2 &= ~PR_O2_CHK_ANY;
4734 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004735
4736 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4737 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4738 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4739 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4740 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4741 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004742 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004743 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4744 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4745 } else {
4746 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4747 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4748 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4749 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4750 }
4751 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004752 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4753 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004754 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004755 else if (!strcmp(args[1], "pgsql-check")) {
4756 /* use PostgreSQL request to check servers' health */
4757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4758 err_code |= ERR_WARN;
4759
4760 free(curproxy->check_req);
4761 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004762 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004763 curproxy->options2 |= PR_O2_PGSQL_CHK;
4764
4765 if (*(args[2])) {
4766 int cur_arg = 2;
4767
4768 while (*(args[cur_arg])) {
4769 if (strcmp(args[cur_arg], "user") == 0) {
4770 char * packet;
4771 uint32_t packet_len;
4772 uint32_t pv;
4773
4774 /* suboption header - needs additional argument for it */
4775 if (*(args[cur_arg+1]) == 0) {
4776 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4777 file, linenum, args[0], args[1], args[cur_arg]);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
4781
4782 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4783 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4784 pv = htonl(0x30000); /* protocol version 3.0 */
4785
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004786 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004787
4788 memcpy(packet + 4, &pv, 4);
4789
4790 /* copy "user" */
4791 memcpy(packet + 8, "user", 4);
4792
4793 /* copy username */
4794 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4795
4796 free(curproxy->check_req);
4797 curproxy->check_req = packet;
4798 curproxy->check_len = packet_len;
4799
4800 packet_len = htonl(packet_len);
4801 memcpy(packet, &packet_len, 4);
4802 cur_arg += 2;
4803 } else {
4804 /* unknown suboption - catchall */
4805 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4806 file, linenum, args[0], args[1]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 }
4810 } /* end while loop */
4811 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004812 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4813 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004814 }
4815
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004816 else if (!strcmp(args[1], "redis-check")) {
4817 /* use REDIS PING request to check servers' health */
4818 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4819 err_code |= ERR_WARN;
4820
4821 free(curproxy->check_req);
4822 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004823 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004824 curproxy->options2 |= PR_O2_REDIS_CHK;
4825
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004826 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004827 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4828 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004829
4830 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4831 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004832 }
4833
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004834 else if (!strcmp(args[1], "mysql-check")) {
4835 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004836 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4837 err_code |= ERR_WARN;
4838
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004839 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004840 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004841 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004842 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004843
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004844 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004845 * const char mysql40_client_auth_pkt[] = {
4846 * "\x0e\x00\x00" // packet length
4847 * "\x01" // packet number
4848 * "\x00\x00" // client capabilities
4849 * "\x00\x00\x01" // max packet
4850 * "haproxy\x00" // username (null terminated string)
4851 * "\x00" // filler (always 0x00)
4852 * "\x01\x00\x00" // packet length
4853 * "\x00" // packet number
4854 * "\x01" // COM_QUIT command
4855 * };
4856 */
4857
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004858 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4859 * const char mysql41_client_auth_pkt[] = {
4860 * "\x0e\x00\x00\" // packet length
4861 * "\x01" // packet number
4862 * "\x00\x00\x00\x00" // client capabilities
4863 * "\x00\x00\x00\x01" // max packet
4864 * "\x21" // character set (UTF-8)
4865 * char[23] // All zeroes
4866 * "haproxy\x00" // username (null terminated string)
4867 * "\x00" // filler (always 0x00)
4868 * "\x01\x00\x00" // packet length
4869 * "\x00" // packet number
4870 * "\x01" // COM_QUIT command
4871 * };
4872 */
4873
4874
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004875 if (*(args[2])) {
4876 int cur_arg = 2;
4877
4878 while (*(args[cur_arg])) {
4879 if (strcmp(args[cur_arg], "user") == 0) {
4880 char *mysqluser;
4881 int packetlen, reqlen, userlen;
4882
4883 /* suboption header - needs additional argument for it */
4884 if (*(args[cur_arg+1]) == 0) {
4885 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4886 file, linenum, args[0], args[1], args[cur_arg]);
4887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
4889 }
4890 mysqluser = args[cur_arg + 1];
4891 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004892
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004893 if (*(args[cur_arg+2])) {
4894 if (!strcmp(args[cur_arg+2], "post-41")) {
4895 packetlen = userlen + 7 + 27;
4896 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004897
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004898 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004899 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004900 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004901
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004902 snprintf(curproxy->check_req, 4, "%c%c%c",
4903 ((unsigned char) packetlen & 0xff),
4904 ((unsigned char) (packetlen >> 8) & 0xff),
4905 ((unsigned char) (packetlen >> 16) & 0xff));
4906
4907 curproxy->check_req[3] = 1;
4908 curproxy->check_req[5] = 130;
4909 curproxy->check_req[11] = 1;
4910 curproxy->check_req[12] = 33;
4911 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4912 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4913 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4914 cur_arg += 3;
4915 } else {
4916 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
4919 }
4920 } else {
4921 packetlen = userlen + 7;
4922 reqlen = packetlen + 9;
4923
4924 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004925 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004926 curproxy->check_len = reqlen;
4927
4928 snprintf(curproxy->check_req, 4, "%c%c%c",
4929 ((unsigned char) packetlen & 0xff),
4930 ((unsigned char) (packetlen >> 8) & 0xff),
4931 ((unsigned char) (packetlen >> 16) & 0xff));
4932
4933 curproxy->check_req[3] = 1;
4934 curproxy->check_req[5] = 128;
4935 curproxy->check_req[8] = 1;
4936 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4937 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4938 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4939 cur_arg += 2;
4940 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004941 } else {
4942 /* unknown suboption - catchall */
4943 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4944 file, linenum, args[0], args[1]);
4945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
4947 }
4948 } /* end while loop */
4949 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004950 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004951 else if (!strcmp(args[1], "ldap-check")) {
4952 /* use LDAP request to check servers' health */
4953 free(curproxy->check_req);
4954 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004955 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004956 curproxy->options2 |= PR_O2_LDAP_CHK;
4957
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004958 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004959 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4960 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004961 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4962 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004963 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004964 else if (!strcmp(args[1], "spop-check")) {
4965 if (curproxy == &defproxy) {
4966 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4967 file, linenum, args[0], args[1]);
4968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
4970 }
4971 if (curproxy->cap & PR_CAP_FE) {
4972 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4973 file, linenum, args[0], args[1]);
4974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
4976 }
4977
4978 /* use SPOE request to check servers' health */
4979 free(curproxy->check_req);
4980 curproxy->check_req = NULL;
4981 curproxy->options2 &= ~PR_O2_CHK_ANY;
4982 curproxy->options2 |= PR_O2_SPOP_CHK;
4983
Christopher Faulet8ef75252017-02-20 22:56:03 +01004984 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01004985 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
4988 }
4989 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4990 goto out;
4991 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004992 else if (!strcmp(args[1], "tcp-check")) {
4993 /* use raw TCPCHK send/expect to check servers' health */
4994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4995 err_code |= ERR_WARN;
4996
4997 free(curproxy->check_req);
4998 curproxy->check_req = NULL;
4999 curproxy->options2 &= ~PR_O2_CHK_ANY;
5000 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005001 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5002 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005003 }
Simon Horman98637e52014-06-20 12:30:16 +09005004 else if (!strcmp(args[1], "external-check")) {
5005 /* excute an external command to check servers' health */
5006 free(curproxy->check_req);
5007 curproxy->check_req = NULL;
5008 curproxy->options2 &= ~PR_O2_CHK_ANY;
5009 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005010 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5011 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005012 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005013 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005014 int cur_arg;
5015
5016 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5017 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005018 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005019
Willy Tarreau87cf5142011-08-19 22:57:24 +02005020 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005021
5022 free(curproxy->fwdfor_hdr_name);
5023 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5024 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5025
5026 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5027 cur_arg = 2;
5028 while (*(args[cur_arg])) {
5029 if (!strcmp(args[cur_arg], "except")) {
5030 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005031 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005032 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5033 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005036 }
5037 /* flush useless bits */
5038 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005039 cur_arg += 2;
5040 } else if (!strcmp(args[cur_arg], "header")) {
5041 /* suboption header - needs additional argument for it */
5042 if (*(args[cur_arg+1]) == 0) {
5043 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5044 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005047 }
5048 free(curproxy->fwdfor_hdr_name);
5049 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5050 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5051 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005052 } else if (!strcmp(args[cur_arg], "if-none")) {
5053 curproxy->options &= ~PR_O_FF_ALWAYS;
5054 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005055 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005056 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005057 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005058 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005061 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005062 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005063 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005064 else if (!strcmp(args[1], "originalto")) {
5065 int cur_arg;
5066
5067 /* insert x-original-to field, but not for the IP address listed as an except.
5068 * set default options (ie: bitfield, header name, etc)
5069 */
5070
5071 curproxy->options |= PR_O_ORGTO;
5072
5073 free(curproxy->orgto_hdr_name);
5074 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5075 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5076
Willy Tarreau87cf5142011-08-19 22:57:24 +02005077 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005078 cur_arg = 2;
5079 while (*(args[cur_arg])) {
5080 if (!strcmp(args[cur_arg], "except")) {
5081 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005082 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 +02005083 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5084 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005087 }
5088 /* flush useless bits */
5089 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5090 cur_arg += 2;
5091 } else if (!strcmp(args[cur_arg], "header")) {
5092 /* suboption header - needs additional argument for it */
5093 if (*(args[cur_arg+1]) == 0) {
5094 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5095 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005098 }
5099 free(curproxy->orgto_hdr_name);
5100 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5101 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5102 cur_arg += 2;
5103 } else {
5104 /* unknown suboption - catchall */
5105 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5106 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005109 }
5110 } /* end while loop */
5111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 else {
5113 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 }
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005119 else if (!strcmp(args[0], "default_backend")) {
5120 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005122
5123 if (*(args[1]) == 0) {
5124 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005127 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005128 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005129 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005130
5131 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5132 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005135 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005137
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005138 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5139 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 +01005140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 /* enable reconnections to dispatch */
5143 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005144
5145 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005148 else if (!strcmp(args[0], "http-reuse")) {
5149 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5150 err_code |= ERR_WARN;
5151
5152 if (strcmp(args[1], "never") == 0) {
5153 /* enable a graceful server shutdown on an HTTP 404 response */
5154 curproxy->options &= ~PR_O_REUSE_MASK;
5155 curproxy->options |= PR_O_REUSE_NEVR;
5156 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5157 goto out;
5158 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005159 else if (strcmp(args[1], "safe") == 0) {
5160 /* enable a graceful server shutdown on an HTTP 404 response */
5161 curproxy->options &= ~PR_O_REUSE_MASK;
5162 curproxy->options |= PR_O_REUSE_SAFE;
5163 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5164 goto out;
5165 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005166 else if (strcmp(args[1], "aggressive") == 0) {
5167 curproxy->options &= ~PR_O_REUSE_MASK;
5168 curproxy->options |= PR_O_REUSE_AGGR;
5169 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5170 goto out;
5171 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005172 else if (strcmp(args[1], "always") == 0) {
5173 /* enable a graceful server shutdown on an HTTP 404 response */
5174 curproxy->options &= ~PR_O_REUSE_MASK;
5175 curproxy->options |= PR_O_REUSE_ALWS;
5176 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5177 goto out;
5178 }
5179 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005180 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
5184 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005185 else if (!strcmp(args[0], "http-check")) {
5186 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005188
5189 if (strcmp(args[1], "disable-on-404") == 0) {
5190 /* enable a graceful server shutdown on an HTTP 404 response */
5191 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005192 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5193 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005194 }
Willy Tarreauef781042010-01-27 11:53:01 +01005195 else if (strcmp(args[1], "send-state") == 0) {
5196 /* enable emission of the apparent state of a server in HTTP checks */
5197 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005198 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5199 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005200 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005201 else if (strcmp(args[1], "expect") == 0) {
5202 const char *ptr_arg;
5203 int cur_arg;
5204
5205 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5206 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
5209 }
5210
5211 cur_arg = 2;
5212 /* consider exclamation marks, sole or at the beginning of a word */
5213 while (*(ptr_arg = args[cur_arg])) {
5214 while (*ptr_arg == '!') {
5215 curproxy->options2 ^= PR_O2_EXP_INV;
5216 ptr_arg++;
5217 }
5218 if (*ptr_arg)
5219 break;
5220 cur_arg++;
5221 }
5222 /* now ptr_arg points to the beginning of a word past any possible
5223 * exclamation mark, and cur_arg is the argument which holds this word.
5224 */
5225 if (strcmp(ptr_arg, "status") == 0) {
5226 if (!*(args[cur_arg + 1])) {
5227 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5228 file, linenum, args[0], args[1], ptr_arg);
5229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231 }
5232 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005233 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005234 curproxy->expect_str = strdup(args[cur_arg + 1]);
5235 }
5236 else if (strcmp(ptr_arg, "string") == 0) {
5237 if (!*(args[cur_arg + 1])) {
5238 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5239 file, linenum, args[0], args[1], ptr_arg);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005244 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005245 curproxy->expect_str = strdup(args[cur_arg + 1]);
5246 }
5247 else if (strcmp(ptr_arg, "rstatus") == 0) {
5248 if (!*(args[cur_arg + 1])) {
5249 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5250 file, linenum, args[0], args[1], ptr_arg);
5251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
5253 }
5254 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005255 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005256 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005257 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005258 free(curproxy->expect_regex);
5259 curproxy->expect_regex = NULL;
5260 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005261 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005262 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5263 error = NULL;
5264 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5265 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5266 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5267 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271 }
5272 else if (strcmp(ptr_arg, "rstring") == 0) {
5273 if (!*(args[cur_arg + 1])) {
5274 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5275 file, linenum, args[0], args[1], ptr_arg);
5276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
5278 }
5279 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005280 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005281 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005282 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005283 free(curproxy->expect_regex);
5284 curproxy->expect_regex = NULL;
5285 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005286 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005287 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5288 error = NULL;
5289 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5290 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5291 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5292 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 }
5297 else {
5298 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5299 file, linenum, args[0], args[1], ptr_arg);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 }
5303 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005304 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005305 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 +02005306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005308 }
5309 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005310 else if (!strcmp(args[0], "tcp-check")) {
5311 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5312 err_code |= ERR_WARN;
5313
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005314 if (strcmp(args[1], "comment") == 0) {
5315 int cur_arg;
5316 struct tcpcheck_rule *tcpcheck;
5317
5318 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005319 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005320 tcpcheck->action = TCPCHK_ACT_COMMENT;
5321
5322 if (!*args[cur_arg + 1]) {
5323 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5324 file, linenum, args[cur_arg]);
5325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
5327 }
5328
5329 tcpcheck->comment = strdup(args[cur_arg + 1]);
5330
5331 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005332 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5333 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005334 }
5335 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005336 const char *ptr_arg;
5337 int cur_arg;
5338 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005339
5340 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005341 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5342 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5343 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5344 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5345 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005346
Willy Tarreau5581c272015-05-13 12:24:53 +02005347 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5348 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5349 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5350 file, linenum);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005353 }
5354
5355 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005356 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005357 tcpcheck->action = TCPCHK_ACT_CONNECT;
5358
5359 /* parsing each parameters to fill up the rule */
5360 while (*(ptr_arg = args[cur_arg])) {
5361 /* tcp port */
5362 if (strcmp(args[cur_arg], "port") == 0) {
5363 if ( (atol(args[cur_arg + 1]) > 65535) ||
5364 (atol(args[cur_arg + 1]) < 1) ){
5365 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5366 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370 tcpcheck->port = atol(args[cur_arg + 1]);
5371 cur_arg += 2;
5372 }
5373 /* send proxy protocol */
5374 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5375 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5376 cur_arg++;
5377 }
5378#ifdef USE_OPENSSL
5379 else if (strcmp(args[cur_arg], "ssl") == 0) {
5380 curproxy->options |= PR_O_TCPCHK_SSL;
5381 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5382 cur_arg++;
5383 }
5384#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005385 /* comment for this tcpcheck line */
5386 else if (strcmp(args[cur_arg], "comment") == 0) {
5387 if (!*args[cur_arg + 1]) {
5388 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5389 file, linenum, args[cur_arg]);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
5393 tcpcheck->comment = strdup(args[cur_arg + 1]);
5394 cur_arg += 2;
5395 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005396 else {
5397#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005398 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 +01005399#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005400 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 +01005401#endif /* USE_OPENSSL */
5402 file, linenum, args[0], args[1], args[cur_arg]);
5403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
5405 }
5406
5407 }
5408
5409 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5410 }
5411 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005412 if (! *(args[2]) ) {
5413 /* SEND string expected */
5414 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5415 file, linenum, args[0], args[1], args[2]);
5416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
5418 } else {
5419 struct tcpcheck_rule *tcpcheck;
5420
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005421 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005422
5423 tcpcheck->action = TCPCHK_ACT_SEND;
5424 tcpcheck->string_len = strlen(args[2]);
5425 tcpcheck->string = strdup(args[2]);
5426 tcpcheck->expect_regex = NULL;
5427
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005428 /* comment for this tcpcheck line */
5429 if (strcmp(args[3], "comment") == 0) {
5430 if (!*args[4]) {
5431 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5432 file, linenum, args[3]);
5433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
5435 }
5436 tcpcheck->comment = strdup(args[4]);
5437 }
5438
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005439 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5440 }
5441 }
5442 else if (strcmp(args[1], "send-binary") == 0) {
5443 if (! *(args[2]) ) {
5444 /* SEND binary string expected */
5445 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5446 file, linenum, args[0], args[1], args[2]);
5447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
5449 } else {
5450 struct tcpcheck_rule *tcpcheck;
5451 char *err = NULL;
5452
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005453 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005454
5455 tcpcheck->action = TCPCHK_ACT_SEND;
5456 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5457 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5458 file, linenum, args[0], args[1], args[2], err);
5459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
5461 }
5462 tcpcheck->expect_regex = NULL;
5463
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005464 /* comment for this tcpcheck line */
5465 if (strcmp(args[3], "comment") == 0) {
5466 if (!*args[4]) {
5467 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5468 file, linenum, args[3]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472 tcpcheck->comment = strdup(args[4]);
5473 }
5474
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005475 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5476 }
5477 }
5478 else if (strcmp(args[1], "expect") == 0) {
5479 const char *ptr_arg;
5480 int cur_arg;
5481 int inverse = 0;
5482
5483 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5484 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
5487 }
5488
5489 cur_arg = 2;
5490 /* consider exclamation marks, sole or at the beginning of a word */
5491 while (*(ptr_arg = args[cur_arg])) {
5492 while (*ptr_arg == '!') {
5493 inverse = !inverse;
5494 ptr_arg++;
5495 }
5496 if (*ptr_arg)
5497 break;
5498 cur_arg++;
5499 }
5500 /* now ptr_arg points to the beginning of a word past any possible
5501 * exclamation mark, and cur_arg is the argument which holds this word.
5502 */
5503 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005504 struct tcpcheck_rule *tcpcheck;
5505 char *err = NULL;
5506
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005507 if (!*(args[cur_arg + 1])) {
5508 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5509 file, linenum, args[0], args[1], ptr_arg);
5510 err_code |= ERR_ALERT | ERR_FATAL;
5511 goto out;
5512 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005513
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005514 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005515
5516 tcpcheck->action = TCPCHK_ACT_EXPECT;
5517 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5518 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5519 file, linenum, args[0], args[1], args[2], err);
5520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522 }
5523 tcpcheck->expect_regex = NULL;
5524 tcpcheck->inverse = inverse;
5525
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005526 /* tcpcheck comment */
5527 cur_arg += 2;
5528 if (strcmp(args[cur_arg], "comment") == 0) {
5529 if (!*args[cur_arg + 1]) {
5530 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5531 file, linenum, args[cur_arg + 1]);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
5535 tcpcheck->comment = strdup(args[cur_arg + 1]);
5536 }
5537
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005538 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5539 }
5540 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005541 struct tcpcheck_rule *tcpcheck;
5542
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005543 if (!*(args[cur_arg + 1])) {
5544 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5545 file, linenum, args[0], args[1], ptr_arg);
5546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005549
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005550 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005551
5552 tcpcheck->action = TCPCHK_ACT_EXPECT;
5553 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5554 tcpcheck->string = strdup(args[cur_arg + 1]);
5555 tcpcheck->expect_regex = NULL;
5556 tcpcheck->inverse = inverse;
5557
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005558 /* tcpcheck comment */
5559 cur_arg += 2;
5560 if (strcmp(args[cur_arg], "comment") == 0) {
5561 if (!*args[cur_arg + 1]) {
5562 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5563 file, linenum, args[cur_arg + 1]);
5564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
5566 }
5567 tcpcheck->comment = strdup(args[cur_arg + 1]);
5568 }
5569
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005570 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5571 }
5572 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005573 struct tcpcheck_rule *tcpcheck;
5574
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005575 if (!*(args[cur_arg + 1])) {
5576 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5577 file, linenum, args[0], args[1], ptr_arg);
5578 err_code |= ERR_ALERT | ERR_FATAL;
5579 goto out;
5580 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005581
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005582 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005583
5584 tcpcheck->action = TCPCHK_ACT_EXPECT;
5585 tcpcheck->string_len = 0;
5586 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005587 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5588 error = NULL;
5589 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5590 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5591 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5592 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
5595 }
5596 tcpcheck->inverse = inverse;
5597
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005598 /* tcpcheck comment */
5599 cur_arg += 2;
5600 if (strcmp(args[cur_arg], "comment") == 0) {
5601 if (!*args[cur_arg + 1]) {
5602 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5603 file, linenum, args[cur_arg + 1]);
5604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 }
5607 tcpcheck->comment = strdup(args[cur_arg + 1]);
5608 }
5609
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005610 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5611 }
5612 else {
5613 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5614 file, linenum, args[0], args[1], ptr_arg);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 }
5618 }
5619 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005620 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005621 err_code |= ERR_ALERT | ERR_FATAL;
5622 goto out;
5623 }
5624 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005625 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005626 if (curproxy == &defproxy) {
5627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005630 }
5631
Willy Tarreaub80c2302007-11-30 20:51:32 +01005632 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005633 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005634
5635 if (strcmp(args[1], "fail") == 0) {
5636 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005637 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005638 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5639 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005642 }
5643
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005644 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5645 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5646 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005649 }
5650 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5651 }
5652 else {
5653 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005656 }
5657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658#ifdef TPROXY
5659 else if (!strcmp(args[0], "transparent")) {
5660 /* enable transparent proxy connections */
5661 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005662 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 }
5665#endif
5666 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005667 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005668 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005669
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 if (*(args[1]) == 0) {
5671 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
5675 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005676 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005678 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005679 else if (!strcmp(args[0], "backlog")) { /* backlog */
5680 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005681 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005682
5683 if (*(args[1]) == 0) {
5684 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005687 }
5688 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005689 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5690 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005691 }
Willy Tarreau86034312006-12-29 00:10:33 +01005692 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005693 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005694 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005695
Willy Tarreau86034312006-12-29 00:10:33 +01005696 if (*(args[1]) == 0) {
5697 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005700 }
5701 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005702 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5703 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5706 if (*(args[1]) == 0) {
5707 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005711 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5712 if (err) {
5713 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5714 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005717 }
5718 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 }
5722 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005723 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005724 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005725 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005726
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 if (curproxy == &defproxy) {
5728 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005732 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005734
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005735 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005736 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005737 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005738 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005739 goto out;
5740 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005741
5742 proto = protocol_by_family(sk->ss_family);
5743 if (!proto || !proto->connect) {
5744 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5745 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
5748 }
5749
5750 if (port1 != port2) {
5751 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5752 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005756
5757 if (!port1) {
5758 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5759 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
5762 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005763
William Lallemanddf1425a2015-04-28 20:17:49 +02005764 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5765 goto out;
5766
Willy Tarreaud5191e72010-02-09 20:50:45 +01005767 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005768 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 }
5770 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005771 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005772 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005773
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005774 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5775 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005780 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005781 /**
5782 * The syntax for hash-type config element is
5783 * hash-type {map-based|consistent} [[<algo>] avalanche]
5784 *
5785 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5786 */
5787 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005788
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005789 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5790 err_code |= ERR_WARN;
5791
5792 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005793 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5794 }
5795 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005796 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5797 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005798 else if (strcmp(args[1], "avalanche") == 0) {
5799 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]);
5800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005802 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005803 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005804 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005805 err_code |= ERR_ALERT | ERR_FATAL;
5806 goto out;
5807 }
Bhaskar98634f02013-10-29 23:30:51 -04005808
5809 /* set the hash function to use */
5810 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005811 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005812 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005813
5814 /* if consistent with no argument, then avalanche modifier is also applied */
5815 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5816 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005817 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005818 /* set the hash function */
5819 if (!strcmp(args[2], "sdbm")) {
5820 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5821 }
5822 else if (!strcmp(args[2], "djb2")) {
5823 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005824 }
5825 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005826 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005827 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005828 else if (!strcmp(args[2], "crc32")) {
5829 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5830 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005831 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005832 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 -05005833 err_code |= ERR_ALERT | ERR_FATAL;
5834 goto out;
5835 }
5836
5837 /* set the hash modifier */
5838 if (!strcmp(args[3], "avalanche")) {
5839 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5840 }
5841 else if (*args[3]) {
5842 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
5845 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005846 }
William Lallemanda73203e2012-03-12 12:48:57 +01005847 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005848 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5849 if (*(args[1]) == 0) {
5850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5851 err_code |= ERR_ALERT | ERR_FATAL;
5852 goto out;
5853 }
5854 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5855 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5856 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
5859 }
5860 }
William Lallemanda73203e2012-03-12 12:48:57 +01005861 else if (strcmp(args[0], "unique-id-format") == 0) {
5862 if (!*(args[1])) {
5863 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
5866 }
William Lallemand3203ff42012-11-11 17:30:56 +01005867 if (*(args[2])) {
5868 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5869 err_code |= ERR_ALERT | ERR_FATAL;
5870 goto out;
5871 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005872 free(curproxy->conf.uniqueid_format_string);
5873 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005874
Willy Tarreau62a61232013-04-12 18:13:46 +02005875 free(curproxy->conf.uif_file);
5876 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5877 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005878 }
William Lallemanda73203e2012-03-12 12:48:57 +01005879
5880 else if (strcmp(args[0], "unique-id-header") == 0) {
5881 if (!*(args[1])) {
5882 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
5885 }
5886 free(curproxy->header_unique_id);
5887 curproxy->header_unique_id = strdup(args[1]);
5888 }
5889
William Lallemand723b73a2012-02-08 16:37:49 +01005890 else if (strcmp(args[0], "log-format") == 0) {
5891 if (!*(args[1])) {
5892 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
5895 }
William Lallemand3203ff42012-11-11 17:30:56 +01005896 if (*(args[2])) {
5897 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5898 err_code |= ERR_ALERT | ERR_FATAL;
5899 goto out;
5900 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005901 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5902 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005903
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005904 if (curproxy->conf.logformat_string == default_http_log_format)
5905 oldlogformat = "option httplog";
5906 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5907 oldlogformat = "option tcplog";
5908 else if (curproxy->conf.logformat_string == clf_http_log_format)
5909 oldlogformat = "option httplog clf";
5910 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5911 file, linenum, oldlogformat);
5912 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005913 if (curproxy->conf.logformat_string != default_http_log_format &&
5914 curproxy->conf.logformat_string != default_tcp_log_format &&
5915 curproxy->conf.logformat_string != clf_http_log_format)
5916 free(curproxy->conf.logformat_string);
5917 curproxy->conf.logformat_string = strdup(args[1]);
5918
5919 free(curproxy->conf.lfs_file);
5920 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5921 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005922
5923 /* get a chance to improve log-format error reporting by
5924 * reporting the correct line-number when possible.
5925 */
5926 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5927 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5928 file, linenum, curproxy->id);
5929 err_code |= ERR_WARN;
5930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005932 else if (!strcmp(args[0], "log-format-sd")) {
5933 if (!*(args[1])) {
5934 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
5937 }
5938 if (*(args[2])) {
5939 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
5942 }
5943
5944 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5945 free(curproxy->conf.logformat_sd_string);
5946 curproxy->conf.logformat_sd_string = strdup(args[1]);
5947
5948 free(curproxy->conf.lfsd_file);
5949 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5950 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5951
5952 /* get a chance to improve log-format-sd error reporting by
5953 * reporting the correct line-number when possible.
5954 */
5955 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5956 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5957 file, linenum, curproxy->id);
5958 err_code |= ERR_WARN;
5959 }
5960 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005961 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5962 if (*(args[1]) == 0) {
5963 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005967 chunk_destroy(&curproxy->log_tag);
5968 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005969 }
William Lallemand0f99e342011-10-12 17:50:54 +02005970 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5971 /* delete previous herited or defined syslog servers */
5972 struct logsrv *back;
5973
5974 if (*(args[1]) != 0) {
5975 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5976 err_code |= ERR_ALERT | ERR_FATAL;
5977 goto out;
5978 }
5979
William Lallemand723b73a2012-02-08 16:37:49 +01005980 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5981 LIST_DEL(&tmplogsrv->list);
5982 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005983 }
5984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005985 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005986 struct logsrv *logsrv;
5987
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005989 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005990 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005991 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005992 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005993 LIST_INIT(&node->list);
5994 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996 }
5997 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005998 struct sockaddr_storage *sk;
5999 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006000 int arg = 0;
6001 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006002
Vincent Bernat02779b62016-04-03 13:48:43 +02006003 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006004
Willy Tarreau18324f52014-06-27 18:10:07 +02006005 /* just after the address, a length may be specified */
6006 if (strcmp(args[arg+2], "len") == 0) {
6007 len = atoi(args[arg+3]);
6008 if (len < 80 || len > 65535) {
6009 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6010 file, linenum, args[arg+3]);
6011 err_code |= ERR_ALERT | ERR_FATAL;
6012 goto out;
6013 }
6014 logsrv->maxlen = len;
6015
6016 /* skip these two args */
6017 arg += 2;
6018 }
6019 else
6020 logsrv->maxlen = MAX_SYSLOG_LEN;
6021
6022 if (logsrv->maxlen > global.max_syslog_len) {
6023 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006024 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6025 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6026 logline = my_realloc2(logline, global.max_syslog_len + 1);
6027 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006028 }
6029
Dragan Dosen1322d092015-09-22 16:05:32 +02006030 /* after the length, a format may be specified */
6031 if (strcmp(args[arg+2], "format") == 0) {
6032 logsrv->format = get_log_format(args[arg+3]);
6033 if (logsrv->format < 0) {
6034 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
6038
6039 /* skip these two args */
6040 arg += 2;
6041 }
6042
William Lallemanddf1425a2015-04-28 20:17:49 +02006043 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6044 goto out;
6045
Willy Tarreau18324f52014-06-27 18:10:07 +02006046 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006047 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006048 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006049 err_code |= ERR_ALERT | ERR_FATAL;
6050 goto out;
6051
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 }
6053
William Lallemand0f99e342011-10-12 17:50:54 +02006054 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006055 if (*(args[arg+3])) {
6056 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006057 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006058 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006059 err_code |= ERR_ALERT | ERR_FATAL;
6060 goto out;
6061
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062 }
6063 }
6064
William Lallemand0f99e342011-10-12 17:50:54 +02006065 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006066 if (*(args[arg+4])) {
6067 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006068 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006069 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006070 err_code |= ERR_ALERT | ERR_FATAL;
6071 goto out;
6072
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006073 }
6074 }
6075
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006076 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006077 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006078 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006079 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006080 goto out;
6081 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006082
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006083 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006084
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006085 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006086 if (port1 != port2) {
6087 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6088 file, linenum, args[0], args[1]);
6089 err_code |= ERR_ALERT | ERR_FATAL;
6090 goto out;
6091 }
6092
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006093 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006094 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006095 }
William Lallemand0f99e342011-10-12 17:50:54 +02006096
6097 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 }
6099 else {
6100 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6101 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006104 }
6105 }
6106 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006107 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006108 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006109 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006110 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006111
Willy Tarreau977b8e42006-12-29 14:19:17 +01006112 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006113 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006114
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006116 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6117 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006118 err_code |= ERR_ALERT | ERR_FATAL;
6119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006121
6122 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006123 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6124 free(curproxy->conn_src.iface_name);
6125 curproxy->conn_src.iface_name = NULL;
6126 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006127
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006128 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006129 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006130 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006131 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006132 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006133 goto out;
6134 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006135
6136 proto = protocol_by_family(sk->ss_family);
6137 if (!proto || !proto->connect) {
6138 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006139 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006140 err_code |= ERR_ALERT | ERR_FATAL;
6141 goto out;
6142 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006143
6144 if (port1 != port2) {
6145 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6146 file, linenum, args[0], args[1]);
6147 err_code |= ERR_ALERT | ERR_FATAL;
6148 goto out;
6149 }
6150
Willy Tarreauef9a3602012-12-08 22:29:20 +01006151 curproxy->conn_src.source_addr = *sk;
6152 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006153
6154 cur_arg = 2;
6155 while (*(args[cur_arg])) {
6156 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006157#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006158 if (!*args[cur_arg + 1]) {
6159 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6160 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006161 err_code |= ERR_ALERT | ERR_FATAL;
6162 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006163 }
6164
6165 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006166 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6167 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006168 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006169 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6170 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006171 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6172 char *name, *end;
6173
6174 name = args[cur_arg+1] + 7;
6175 while (isspace(*name))
6176 name++;
6177
6178 end = name;
6179 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6180 end++;
6181
Willy Tarreauef9a3602012-12-08 22:29:20 +01006182 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6183 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6184 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6185 curproxy->conn_src.bind_hdr_len = end - name;
6186 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6187 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6188 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006189
6190 /* now look for an occurrence number */
6191 while (isspace(*end))
6192 end++;
6193 if (*end == ',') {
6194 end++;
6195 name = end;
6196 if (*end == '-')
6197 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006198 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006199 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006200 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006201 }
6202
Willy Tarreauef9a3602012-12-08 22:29:20 +01006203 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006204 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6205 " occurrences values smaller than %d.\n",
6206 file, linenum, MAX_HDR_HISTORY);
6207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
6209 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006210 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006211 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006212
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006213 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006214 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006215 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006216 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006217 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006218 goto out;
6219 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006220
6221 proto = protocol_by_family(sk->ss_family);
6222 if (!proto || !proto->connect) {
6223 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6224 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006225 err_code |= ERR_ALERT | ERR_FATAL;
6226 goto out;
6227 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006228
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006229 if (port1 != port2) {
6230 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6231 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006235 curproxy->conn_src.tproxy_addr = *sk;
6236 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006237 }
6238 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006239#else /* no TPROXY support */
6240 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006241 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006242 err_code |= ERR_ALERT | ERR_FATAL;
6243 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006244#endif
6245 cur_arg += 2;
6246 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006247 }
6248
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006249 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6250#ifdef SO_BINDTODEVICE
6251 if (!*args[cur_arg + 1]) {
6252 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006254 err_code |= ERR_ALERT | ERR_FATAL;
6255 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006256 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006257 free(curproxy->conn_src.iface_name);
6258 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6259 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006260 global.last_checks |= LSTCHK_NETADM;
6261#else
6262 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6263 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006266#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006267 cur_arg += 2;
6268 continue;
6269 }
6270 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006271 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006272 err_code |= ERR_ALERT | ERR_FATAL;
6273 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006275 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006276 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6277 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6278 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006283 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006284 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006286 err_code |= ERR_ALERT | ERR_FATAL;
6287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006288 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006289
6290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006291 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006292 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 }
6296 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006298 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 }
6303 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006305 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 }
6310 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006312 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006313 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 }
6317 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006319 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006320 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006321 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006324 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006326 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006327 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006329 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006331 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006332 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6334 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006335 err_code |= ERR_ALERT | ERR_FATAL;
6336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006338
6339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006340 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006341 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
6345 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006347 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006348 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
6366 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006373 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006375 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006376 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006378 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006379 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006381 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006382
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 if (curproxy == &defproxy) {
6384 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006388 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006389 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 if (*(args[1]) == 0) {
6392 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006393 err_code |= ERR_ALERT | ERR_FATAL;
6394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006396
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006397 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006398 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6399 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6400 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006401 err_code |= ERR_ALERT | ERR_FATAL;
6402 goto out;
6403 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006404 err_code |= warnif_cond_conflicts(cond,
6405 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6406 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006407 }
6408 else if (*args[2]) {
6409 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6410 file, linenum, args[0], args[2]);
6411 err_code |= ERR_ALERT | ERR_FATAL;
6412 goto out;
6413 }
6414
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006415 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006416 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006417 wl->s = strdup(args[1]);
6418 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006419 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
6421 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6424 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006425 err_code |= ERR_ALERT | ERR_FATAL;
6426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006428
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006430 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006431 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
6435 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006437 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006438 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
6442 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006443 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006444 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006445 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006446 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
6449 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6452 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
6456
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006458 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006459 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006460 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006465 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006466 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006472 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006473 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
6477 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006478 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006479
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 if (curproxy == &defproxy) {
6481 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006485 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006486 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 if (*(args[1]) == 0) {
6489 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006490 err_code |= ERR_ALERT | ERR_FATAL;
6491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006492 }
6493
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006494 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006495 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6496 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6497 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006498 err_code |= ERR_ALERT | ERR_FATAL;
6499 goto out;
6500 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006501 err_code |= warnif_cond_conflicts(cond,
6502 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6503 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006504 }
6505 else if (*args[2]) {
6506 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6507 file, linenum, args[0], args[2]);
6508 err_code |= ERR_ALERT | ERR_FATAL;
6509 goto out;
6510 }
6511
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006512 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006513 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006514 wl->s = strdup(args[1]);
6515 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 }
6517 else if (!strcmp(args[0], "errorloc") ||
6518 !strcmp(args[0], "errorloc302") ||
6519 !strcmp(args[0], "errorloc303")) { /* error location */
6520 int errnum, errlen;
6521 char *err;
6522
Willy Tarreau977b8e42006-12-29 14:19:17 +01006523 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006524 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006525
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006527 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006528 err_code |= ERR_ALERT | ERR_FATAL;
6529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 }
6531
6532 errnum = atol(args[1]);
6533 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006534 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6535 err = malloc(errlen);
6536 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006538 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6539 err = malloc(errlen);
6540 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 }
6542
Willy Tarreau0f772532006-12-23 20:51:41 +01006543 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6544 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006545 chunk_destroy(&curproxy->errmsg[rc]);
6546 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006547 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006550
6551 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006552 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6553 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006554 free(err);
6555 }
6556 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006557 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6558 int errnum, errlen, fd;
6559 char *err;
6560 struct stat stat;
6561
6562 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006563 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006564
6565 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006566 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006567 err_code |= ERR_ALERT | ERR_FATAL;
6568 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006569 }
6570
6571 fd = open(args[2], O_RDONLY);
6572 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6573 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6574 file, linenum, args[2], args[1]);
6575 if (fd >= 0)
6576 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006577 err_code |= ERR_ALERT | ERR_FATAL;
6578 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006579 }
6580
Willy Tarreau27a674e2009-08-17 07:23:33 +02006581 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006582 errlen = stat.st_size;
6583 } else {
6584 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006585 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006586 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006587 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006588 }
6589
6590 err = malloc(errlen); /* malloc() must succeed during parsing */
6591 errnum = read(fd, err, errlen);
6592 if (errnum != errlen) {
6593 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6594 file, linenum, args[2], args[1]);
6595 close(fd);
6596 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006597 err_code |= ERR_ALERT | ERR_FATAL;
6598 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006599 }
6600 close(fd);
6601
6602 errnum = atol(args[1]);
6603 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6604 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006605 chunk_destroy(&curproxy->errmsg[rc]);
6606 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006607 break;
6608 }
6609 }
6610
6611 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006612 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6613 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006614 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006615 free(err);
6616 }
6617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006618 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006619 struct cfg_kw_list *kwl;
6620 int index;
6621
6622 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6623 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6624 if (kwl->kw[index].section != CFG_LISTEN)
6625 continue;
6626 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6627 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006628 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006629 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006630 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006631 err_code |= ERR_ALERT | ERR_FATAL;
6632 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006633 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006634 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006635 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006636 err_code |= ERR_WARN;
6637 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006638 }
Willy Tarreau93893792009-07-23 13:19:11 +02006639 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006640 }
6641 }
6642 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006643
Willy Tarreau6daf3432008-01-22 16:44:08 +01006644 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006645 err_code |= ERR_ALERT | ERR_FATAL;
6646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006647 }
Willy Tarreau93893792009-07-23 13:19:11 +02006648 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006649 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006650 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006651}
6652
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006653int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006654cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6655{
6656#ifdef CONFIG_HAP_NS
6657 const char *err;
6658 const char *item = args[0];
6659
6660 if (!strcmp(item, "namespace_list")) {
6661 return 0;
6662 }
6663 else if (!strcmp(item, "namespace")) {
6664 size_t idx = 1;
6665 const char *current;
6666 while (*(current = args[idx++])) {
6667 err = invalid_char(current);
6668 if (err) {
6669 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6670 file, linenum, *err, item, current);
6671 return ERR_ALERT | ERR_FATAL;
6672 }
6673
6674 if (netns_store_lookup(current, strlen(current))) {
6675 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6676 file, linenum, current);
6677 return ERR_ALERT | ERR_FATAL;
6678 }
6679 if (!netns_store_insert(current)) {
6680 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6681 file, linenum, current);
6682 return ERR_ALERT | ERR_FATAL;
6683 }
6684 }
6685 }
6686
6687 return 0;
6688#else
6689 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6690 file, linenum);
6691 return ERR_ALERT | ERR_FATAL;
6692#endif
6693}
6694
6695int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006696cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6697{
6698
6699 int err_code = 0;
6700 const char *err;
6701
6702 if (!strcmp(args[0], "userlist")) { /* new userlist */
6703 struct userlist *newul;
6704
6705 if (!*args[1]) {
6706 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6707 file, linenum, args[0]);
6708 err_code |= ERR_ALERT | ERR_FATAL;
6709 goto out;
6710 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006711 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6712 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006713
6714 err = invalid_char(args[1]);
6715 if (err) {
6716 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6717 file, linenum, *err, args[0], args[1]);
6718 err_code |= ERR_ALERT | ERR_FATAL;
6719 goto out;
6720 }
6721
6722 for (newul = userlist; newul; newul = newul->next)
6723 if (!strcmp(newul->name, args[1])) {
6724 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6725 file, linenum, args[1]);
6726 err_code |= ERR_WARN;
6727 goto out;
6728 }
6729
Vincent Bernat02779b62016-04-03 13:48:43 +02006730 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006731 if (!newul) {
6732 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6733 err_code |= ERR_ALERT | ERR_ABORT;
6734 goto out;
6735 }
6736
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006737 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006738 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006739 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6740 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006741 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742 goto out;
6743 }
6744
6745 newul->next = userlist;
6746 userlist = newul;
6747
6748 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006749 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006750 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006751 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006752
6753 if (!*args[1]) {
6754 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6755 file, linenum, args[0]);
6756 err_code |= ERR_ALERT | ERR_FATAL;
6757 goto out;
6758 }
6759
6760 err = invalid_char(args[1]);
6761 if (err) {
6762 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6763 file, linenum, *err, args[0], args[1]);
6764 err_code |= ERR_ALERT | ERR_FATAL;
6765 goto out;
6766 }
6767
William Lallemand4ac9f542015-05-28 18:03:51 +02006768 if (!userlist)
6769 goto out;
6770
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006771 for (ag = userlist->groups; ag; ag = ag->next)
6772 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006773 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6774 file, linenum, args[1], userlist->name);
6775 err_code |= ERR_ALERT;
6776 goto out;
6777 }
6778
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006779 ag = calloc(1, sizeof(*ag));
6780 if (!ag) {
6781 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6782 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006783 goto out;
6784 }
6785
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006786 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006787 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006788 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6789 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006790 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006791 goto out;
6792 }
6793
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006794 cur_arg = 2;
6795
6796 while (*args[cur_arg]) {
6797 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006798 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006799 cur_arg += 2;
6800 continue;
6801 } else {
6802 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6803 file, linenum, args[0]);
6804 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006805 free(ag->groupusers);
6806 free(ag->name);
6807 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006808 goto out;
6809 }
6810 }
6811
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006812 ag->next = userlist->groups;
6813 userlist->groups = ag;
6814
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006815 } else if (!strcmp(args[0], "user")) { /* new user */
6816 struct auth_users *newuser;
6817 int cur_arg;
6818
6819 if (!*args[1]) {
6820 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6821 file, linenum, args[0]);
6822 err_code |= ERR_ALERT | ERR_FATAL;
6823 goto out;
6824 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006825 if (!userlist)
6826 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006827
6828 for (newuser = userlist->users; newuser; newuser = newuser->next)
6829 if (!strcmp(newuser->user, args[1])) {
6830 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6831 file, linenum, args[1], userlist->name);
6832 err_code |= ERR_ALERT;
6833 goto out;
6834 }
6835
Vincent Bernat02779b62016-04-03 13:48:43 +02006836 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006837 if (!newuser) {
6838 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6839 err_code |= ERR_ALERT | ERR_ABORT;
6840 goto out;
6841 }
6842
6843 newuser->user = strdup(args[1]);
6844
6845 newuser->next = userlist->users;
6846 userlist->users = newuser;
6847
6848 cur_arg = 2;
6849
6850 while (*args[cur_arg]) {
6851 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006852#ifdef CONFIG_HAP_CRYPT
6853 if (!crypt("", args[cur_arg + 1])) {
6854 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6855 file, linenum, newuser->user);
6856 err_code |= ERR_ALERT | ERR_FATAL;
6857 goto out;
6858 }
6859#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006860 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6861 file, linenum);
6862 err_code |= ERR_ALERT;
6863#endif
6864 newuser->pass = strdup(args[cur_arg + 1]);
6865 cur_arg += 2;
6866 continue;
6867 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6868 newuser->pass = strdup(args[cur_arg + 1]);
6869 newuser->flags |= AU_O_INSECURE;
6870 cur_arg += 2;
6871 continue;
6872 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006873 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006874 cur_arg += 2;
6875 continue;
6876 } else {
6877 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6878 file, linenum, args[0]);
6879 err_code |= ERR_ALERT | ERR_FATAL;
6880 goto out;
6881 }
6882 }
6883 } else {
6884 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6885 err_code |= ERR_ALERT | ERR_FATAL;
6886 }
6887
6888out:
6889 return err_code;
6890}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006891
Christopher Faulet79bdef32016-11-04 22:36:15 +01006892int
6893cfg_parse_scope(const char *file, int linenum, char *line)
6894{
6895 char *beg, *end, *scope = NULL;
6896 int err_code = 0;
6897 const char *err;
6898
6899 beg = line + 1;
6900 end = strchr(beg, ']');
6901
6902 /* Detect end of scope declaration */
6903 if (!end || end == beg) {
6904 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6905 file, linenum);
6906 err_code |= ERR_ALERT | ERR_FATAL;
6907 goto out;
6908 }
6909
6910 /* Get scope name and check its validity */
6911 scope = my_strndup(beg, end-beg);
6912 err = invalid_char(scope);
6913 if (err) {
6914 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6915 file, linenum, *err);
6916 err_code |= ERR_ALERT | ERR_ABORT;
6917 goto out;
6918 }
6919
6920 /* Be sure to have a scope declaration alone on its line */
6921 line = end+1;
6922 while (isspace((unsigned char)*line))
6923 line++;
6924 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6925 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6926 file, linenum, *line);
6927 err_code |= ERR_ALERT | ERR_ABORT;
6928 goto out;
6929 }
6930
6931 /* We have a valid scope declaration, save it */
6932 free(cfg_scope);
6933 cfg_scope = scope;
6934 scope = NULL;
6935
6936 out:
6937 free(scope);
6938 return err_code;
6939}
6940
Willy Tarreaubaaee002006-06-26 02:48:02 +02006941/*
6942 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006943 * Returns the error code, 0 if OK, or any combination of :
6944 * - ERR_ABORT: must abort ASAP
6945 * - ERR_FATAL: we can continue parsing but not start the service
6946 * - ERR_WARN: a warning has been emitted
6947 * - ERR_ALERT: an alert has been emitted
6948 * Only the two first ones can stop processing, the two others are just
6949 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006951int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006952{
William Lallemand64e84512015-05-12 14:25:37 +02006953 char *thisline;
6954 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006955 FILE *f;
6956 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006957 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006958 struct cfg_section *cs = NULL;
6959 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006960 int readbytes = 0;
6961
6962 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006963 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006964 return -1;
6965 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006966
David Carlier97880bb2016-04-08 10:35:26 +01006967 if ((f=fopen(file,"r")) == NULL) {
6968 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006969 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006971
William Lallemandb2f07452015-05-12 14:27:13 +02006972next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006973 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006974 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006975 char *end;
6976 char *args[MAX_LINE_ARGS + 1];
6977 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006978 int dquote = 0; /* double quote */
6979 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006980
Willy Tarreaubaaee002006-06-26 02:48:02 +02006981 linenum++;
6982
6983 end = line + strlen(line);
6984
William Lallemand64e84512015-05-12 14:25:37 +02006985 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006986 /* Check if we reached the limit and the last char is not \n.
6987 * Watch out for the last line without the terminating '\n'!
6988 */
William Lallemand64e84512015-05-12 14:25:37 +02006989 char *newline;
6990 int newlinesize = linesize * 2;
6991
6992 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6993 if (newline == NULL) {
6994 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6995 file, linenum);
6996 err_code |= ERR_ALERT | ERR_FATAL;
6997 continue;
6998 }
6999
7000 readbytes = linesize - 1;
7001 linesize = newlinesize;
7002 thisline = newline;
7003 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007004 }
7005
William Lallemand64e84512015-05-12 14:25:37 +02007006 readbytes = 0;
7007
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007009 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007011
Christopher Faulet79bdef32016-11-04 22:36:15 +01007012
7013 if (*line == '[') {/* This is the begining if a scope */
7014 err_code |= cfg_parse_scope(file, linenum, line);
7015 goto next_line;
7016 }
7017
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 arg = 0;
7019 args[arg] = line;
7020
7021 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007022 if (*line == '"' && !squote) { /* double quote outside single quotes */
7023 if (dquote)
7024 dquote = 0;
7025 else
7026 dquote = 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 == '\'' && !dquote) { /* single quote outside double quotes */
7031 if (squote)
7032 squote = 0;
7033 else
7034 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007035 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007036 end--;
7037 }
7038 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7040 * C equivalent value. Other combinations left unchanged (eg: \1).
7041 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007042 int skip = 0;
7043 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7044 *line = line[1];
7045 skip = 1;
7046 }
7047 else if (line[1] == 'r') {
7048 *line = '\r';
7049 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007051 else if (line[1] == 'n') {
7052 *line = '\n';
7053 skip = 1;
7054 }
7055 else if (line[1] == 't') {
7056 *line = '\t';
7057 skip = 1;
7058 }
7059 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007060 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007061 unsigned char hex1, hex2;
7062 hex1 = toupper(line[2]) - '0';
7063 hex2 = toupper(line[3]) - '0';
7064 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7065 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7066 *line = (hex1<<4) + hex2;
7067 skip = 3;
7068 }
7069 else {
7070 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007071 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007072 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007073 } else if (line[1] == '"') {
7074 *line = '"';
7075 skip = 1;
7076 } else if (line[1] == '\'') {
7077 *line = '\'';
7078 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007079 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7080 *line = '$';
7081 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007082 }
7083 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007084 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007085 end -= skip;
7086 }
7087 line++;
7088 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007089 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007090 /* end of string, end of loop */
7091 *line = 0;
7092 break;
7093 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007094 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007096 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007097 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007098 line++;
7099 args[++arg] = line;
7100 }
William Lallemandb2f07452015-05-12 14:27:13 +02007101 else if (dquote && *line == '$') {
7102 /* environment variables are evaluated inside double quotes */
7103 char *var_beg;
7104 char *var_end;
7105 char save_char;
7106 char *value;
7107 int val_len;
7108 int newlinesize;
7109 int braces = 0;
7110
7111 var_beg = line + 1;
7112 var_end = var_beg;
7113
7114 if (*var_beg == '{') {
7115 var_beg++;
7116 var_end++;
7117 braces = 1;
7118 }
7119
7120 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7121 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7122 err_code |= ERR_ALERT | ERR_FATAL;
7123 goto next_line; /* skip current line */
7124 }
7125
7126 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7127 var_end++;
7128
7129 save_char = *var_end;
7130 *var_end = '\0';
7131 value = getenv(var_beg);
7132 *var_end = save_char;
7133 val_len = value ? strlen(value) : 0;
7134
7135 if (braces) {
7136 if (*var_end == '}') {
7137 var_end++;
7138 braces = 0;
7139 } else {
7140 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7141 err_code |= ERR_ALERT | ERR_FATAL;
7142 goto next_line; /* skip current line */
7143 }
7144 }
7145
7146 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7147
7148 /* if not enough space in thisline */
7149 if (newlinesize > linesize) {
7150 char *newline;
7151
7152 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7153 if (newline == NULL) {
7154 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7155 err_code |= ERR_ALERT | ERR_FATAL;
7156 goto next_line; /* slip current line */
7157 }
7158 /* recompute pointers if realloc returns a new pointer */
7159 if (newline != thisline) {
7160 int i;
7161 int diff;
7162
7163 for (i = 0; i <= arg; i++) {
7164 diff = args[i] - thisline;
7165 args[i] = newline + diff;
7166 }
7167
7168 diff = var_end - thisline;
7169 var_end = newline + diff;
7170 diff = end - thisline;
7171 end = newline + diff;
7172 diff = line - thisline;
7173 line = newline + diff;
7174 thisline = newline;
7175 }
7176 linesize = newlinesize;
7177 }
7178
7179 /* insert value inside the line */
7180 memmove(line + val_len, var_end, end - var_end + 1);
7181 memcpy(line, value, val_len);
7182 end += val_len - (var_end - line);
7183 line += val_len;
7184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007185 else {
7186 line++;
7187 }
7188 }
William Lallemandb2f07452015-05-12 14:27:13 +02007189
William Lallemandf9873ba2015-05-05 17:37:14 +02007190 if (dquote) {
7191 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7192 err_code |= ERR_ALERT | ERR_FATAL;
7193 }
7194
7195 if (squote) {
7196 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7197 err_code |= ERR_ALERT | ERR_FATAL;
7198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007199
7200 /* empty line */
7201 if (!**args)
7202 continue;
7203
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007204 if (*line) {
7205 /* we had to stop due to too many args.
7206 * Let's terminate the string, print the offending part then cut the
7207 * last arg.
7208 */
7209 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7210 line++;
7211 *line = '\0';
7212
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007213 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007214 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007215 err_code |= ERR_ALERT | ERR_FATAL;
7216 args[arg] = line;
7217 }
7218
Willy Tarreau540abe42007-05-02 20:50:16 +02007219 /* zero out remaining args and ensure that at least one entry
7220 * is zeroed out.
7221 */
7222 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007223 args[arg] = line;
7224 }
7225
Willy Tarreau3842f002009-06-14 11:39:52 +02007226 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007227 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007228 char *tmp;
7229
Willy Tarreau3842f002009-06-14 11:39:52 +02007230 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007231 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007232 for (arg=0; *args[arg+1]; arg++)
7233 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007234 *tmp = '\0'; // fix the next arg to \0
7235 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007236 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007237 else if (!strcmp(args[0], "default")) {
7238 kwm = KWM_DEF;
7239 for (arg=0; *args[arg+1]; arg++)
7240 args[arg] = args[arg+1]; // shift args after inversion
7241 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007242
William Lallemand0f99e342011-10-12 17:50:54 +02007243 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7244 strcmp(args[0], "log") != 0) {
7245 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007246 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007247 }
7248
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007249 /* detect section start */
7250 list_for_each_entry(ics, &sections, list) {
7251 if (strcmp(args[0], ics->section_name) == 0) {
7252 cursection = ics->section_name;
7253 cs = ics;
7254 break;
7255 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007256 }
7257
Willy Tarreaubaaee002006-06-26 02:48:02 +02007258 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007259 if (cs)
7260 err_code |= cs->section_parser(file, linenum, args, kwm);
7261 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007262 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007263 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007264 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007265
7266 if (err_code & ERR_ABORT)
7267 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007268 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007269 free(cfg_scope);
7270 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007271 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007272 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007273 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007274 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007275}
7276
Willy Tarreau64ab6072014-09-16 12:17:36 +02007277/* This function propagates processes from frontend <from> to backend <to> so
7278 * that it is always guaranteed that a backend pointed to by a frontend is
7279 * bound to all of its processes. After that, if the target is a "listen"
7280 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007281 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007282 * checked first to ensure that <to> is already bound to all processes of
7283 * <from>, there is no risk of looping and we ensure to follow the shortest
7284 * path to the destination.
7285 *
7286 * It is possible to set <to> to NULL for the first call so that the function
7287 * takes care of visiting the initial frontend in <from>.
7288 *
7289 * It is important to note that the function relies on the fact that all names
7290 * have already been resolved.
7291 */
7292void propagate_processes(struct proxy *from, struct proxy *to)
7293{
7294 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007295
7296 if (to) {
7297 /* check whether we need to go down */
7298 if (from->bind_proc &&
7299 (from->bind_proc & to->bind_proc) == from->bind_proc)
7300 return;
7301
7302 if (!from->bind_proc && !to->bind_proc)
7303 return;
7304
7305 to->bind_proc = from->bind_proc ?
7306 (to->bind_proc | from->bind_proc) : 0;
7307
7308 /* now propagate down */
7309 from = to;
7310 }
7311
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007312 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007313 return;
7314
Willy Tarreauf6b70012014-12-18 14:00:43 +01007315 if (from->state == PR_STSTOPPED)
7316 return;
7317
Willy Tarreau64ab6072014-09-16 12:17:36 +02007318 /* default_backend */
7319 if (from->defbe.be)
7320 propagate_processes(from, from->defbe.be);
7321
7322 /* use_backend */
7323 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007324 if (rule->dynamic)
7325 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007326 to = rule->be.backend;
7327 propagate_processes(from, to);
7328 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007329}
7330
Willy Tarreaubb925012009-07-23 13:36:36 +02007331/*
7332 * Returns the error code, 0 if OK, or any combination of :
7333 * - ERR_ABORT: must abort ASAP
7334 * - ERR_FATAL: we can continue parsing but not start the service
7335 * - ERR_WARN: a warning has been emitted
7336 * - ERR_ALERT: an alert has been emitted
7337 * Only the two first ones can stop processing, the two others are just
7338 * indicators.
7339 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007340int check_config_validity()
7341{
7342 int cfgerr = 0;
7343 struct proxy *curproxy = NULL;
7344 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007345 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007346 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007347 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007348 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007349
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007350 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007351 /*
7352 * Now, check for the integrity of all that we have collected.
7353 */
7354
7355 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007356 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007357
Willy Tarreau193b8c62012-11-22 00:17:38 +01007358 if (!global.tune.max_http_hdr)
7359 global.tune.max_http_hdr = MAX_HTTP_HDR;
7360
7361 if (!global.tune.cookie_len)
7362 global.tune.cookie_len = CAPTURE_LEN;
7363
7364 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7365
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007366 /* Post initialisation of the users and groups lists. */
7367 err_code = userlist_postinit();
7368 if (err_code != ERR_NONE)
7369 goto out;
7370
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007371 /* first, we will invert the proxy list order */
7372 curproxy = NULL;
7373 while (proxy) {
7374 struct proxy *next;
7375
7376 next = proxy->next;
7377 proxy->next = curproxy;
7378 curproxy = proxy;
7379 if (!next)
7380 break;
7381 proxy = next;
7382 }
7383
Willy Tarreau419ead82014-09-16 13:41:21 +02007384 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007385 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007386 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007387 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007388 struct act_rule *trule;
7389 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007390 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007391 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007392 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007393
Willy Tarreau050536d2012-10-04 08:47:34 +02007394 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007395 /* proxy ID not set, use automatic numbering with first
7396 * spare entry starting with next_pxid.
7397 */
7398 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7399 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7400 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007401 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007402 next_pxid++;
7403
Willy Tarreau55ea7572007-06-17 19:56:27 +02007404
Willy Tarreaubaaee002006-06-26 02:48:02 +02007405 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007406 /* ensure we don't keep listeners uselessly bound */
7407 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007408 free((void *)curproxy->table.peers.name);
7409 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007410 continue;
7411 }
7412
Willy Tarreau102df612014-05-07 23:56:38 +02007413 /* Check multi-process mode compatibility for the current proxy */
7414
7415 if (curproxy->bind_proc) {
7416 /* an explicit bind-process was specified, let's check how many
7417 * processes remain.
7418 */
David Carliere6c39412015-07-02 07:00:17 +00007419 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007420
7421 curproxy->bind_proc &= nbits(global.nbproc);
7422 if (!curproxy->bind_proc && nbproc == 1) {
7423 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);
7424 curproxy->bind_proc = 1;
7425 }
7426 else if (!curproxy->bind_proc && nbproc > 1) {
7427 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);
7428 curproxy->bind_proc = 0;
7429 }
7430 }
7431
Willy Tarreau3d209582014-05-09 17:06:11 +02007432 /* check and reduce the bind-proc of each listener */
7433 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7434 unsigned long mask;
7435
7436 if (!bind_conf->bind_proc)
7437 continue;
7438
7439 mask = nbits(global.nbproc);
7440 if (curproxy->bind_proc)
7441 mask &= curproxy->bind_proc;
7442 /* mask cannot be null here thanks to the previous checks */
7443
David Carliere6c39412015-07-02 07:00:17 +00007444 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007445 bind_conf->bind_proc &= mask;
7446
7447 if (!bind_conf->bind_proc && nbproc == 1) {
7448 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",
7449 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7450 bind_conf->bind_proc = mask & ~(mask - 1);
7451 }
7452 else if (!bind_conf->bind_proc && nbproc > 1) {
7453 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",
7454 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7455 bind_conf->bind_proc = 0;
7456 }
7457 }
7458
Willy Tarreauff01a212009-03-15 13:46:16 +01007459 switch (curproxy->mode) {
7460 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007461 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007462 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007463 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7464 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007465 cfgerr++;
7466 }
7467
7468 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007469 Warning("config : servers will be ignored for %s '%s'.\n",
7470 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007471 break;
7472
7473 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007474 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007475 break;
7476
7477 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007478 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007479 break;
7480 }
7481
Willy Tarreauf3934b82015-08-11 11:36:45 +02007482 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7483 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7484 proxy_type_str(curproxy), curproxy->id);
7485 err_code |= ERR_WARN;
7486 }
7487
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007488 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007489 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007490 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007491 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7492 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007493 cfgerr++;
7494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007495#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007496 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007497 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7498 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007499 cfgerr++;
7500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007501#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007502 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007503 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7504 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007505 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007506 }
7507 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007508 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007509 /* If no LB algo is set in a backend, and we're not in
7510 * transparent mode, dispatch mode nor proxy mode, we
7511 * want to use balance roundrobin by default.
7512 */
7513 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7514 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007515 }
7516 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007517
Willy Tarreau1620ec32011-08-06 17:05:02 +02007518 if (curproxy->options & PR_O_DISPATCH)
7519 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7520 else if (curproxy->options & PR_O_HTTP_PROXY)
7521 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7522 else if (curproxy->options & PR_O_TRANSP)
7523 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007524
Willy Tarreau1620ec32011-08-06 17:05:02 +02007525 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7526 if (curproxy->options & PR_O_DISABLE404) {
7527 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7528 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7529 err_code |= ERR_WARN;
7530 curproxy->options &= ~PR_O_DISABLE404;
7531 }
7532 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7533 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7534 "send-state", proxy_type_str(curproxy), curproxy->id);
7535 err_code |= ERR_WARN;
7536 curproxy->options &= ~PR_O2_CHK_SNDST;
7537 }
Willy Tarreauef781042010-01-27 11:53:01 +01007538 }
7539
Simon Horman98637e52014-06-20 12:30:16 +09007540 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7541 if (!global.external_check) {
7542 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7543 curproxy->id, "option external-check");
7544 cfgerr++;
7545 }
7546 if (!curproxy->check_command) {
7547 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7548 curproxy->id, "option external-check");
7549 cfgerr++;
7550 }
7551 }
7552
Simon Horman64e34162015-02-06 11:11:57 +09007553 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007554 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7555 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007556 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7557 "'email-alert myhostname', or 'email-alert to' "
7558 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007559 "to be present).\n",
7560 proxy_type_str(curproxy), curproxy->id);
7561 err_code |= ERR_WARN;
7562 free_email_alert(curproxy);
7563 }
7564 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007565 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007566 }
7567
Simon Horman98637e52014-06-20 12:30:16 +09007568 if (curproxy->check_command) {
7569 int clear = 0;
7570 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7571 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7572 "external-check command", proxy_type_str(curproxy), curproxy->id);
7573 err_code |= ERR_WARN;
7574 clear = 1;
7575 }
7576 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007577 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007578 curproxy->id, "external-check command");
7579 cfgerr++;
7580 }
7581 if (clear) {
7582 free(curproxy->check_command);
7583 curproxy->check_command = NULL;
7584 }
7585 }
7586
7587 if (curproxy->check_path) {
7588 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7589 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7590 "external-check path", proxy_type_str(curproxy), curproxy->id);
7591 err_code |= ERR_WARN;
7592 free(curproxy->check_path);
7593 curproxy->check_path = NULL;
7594 }
7595 }
7596
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007597 /* if a default backend was specified, let's find it */
7598 if (curproxy->defbe.name) {
7599 struct proxy *target;
7600
Willy Tarreauafb39922015-05-26 12:04:09 +02007601 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007602 if (!target) {
7603 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7604 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007605 cfgerr++;
7606 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007607 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7608 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007609 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007610 } else if (target->mode != curproxy->mode &&
7611 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7612
7613 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7614 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7615 curproxy->conf.file, curproxy->conf.line,
7616 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7617 target->conf.file, target->conf.line);
7618 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007619 } else {
7620 free(curproxy->defbe.name);
7621 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007622 /* Update tot_fe_maxconn for a further fullconn's computation */
7623 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007624 /* Emit a warning if this proxy also has some servers */
7625 if (curproxy->srv) {
7626 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7627 curproxy->id);
7628 err_code |= ERR_WARN;
7629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007630 }
7631 }
7632
Emeric Brun3f783572017-01-12 11:21:28 +01007633 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7634 /* Case of listen without default backend
7635 * The curproxy will be its own default backend
7636 * so we update tot_fe_maxconn for a further
7637 * fullconn's computation */
7638 curproxy->tot_fe_maxconn += curproxy->maxconn;
7639 }
7640
Willy Tarreau55ea7572007-06-17 19:56:27 +02007641 /* find the target proxy for 'use_backend' rules */
7642 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007643 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007644 struct logformat_node *node;
7645 char *pxname;
7646
7647 /* Try to parse the string as a log format expression. If the result
7648 * of the parsing is only one entry containing a simple string, then
7649 * it's a standard string corresponding to a static rule, thus the
7650 * parsing is cancelled and be.name is restored to be resolved.
7651 */
7652 pxname = rule->be.name;
7653 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007654 curproxy->conf.args.ctx = ARGC_UBK;
7655 curproxy->conf.args.file = rule->file;
7656 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007657 err = NULL;
7658 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7659 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7660 rule->file, rule->line, pxname, err);
7661 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007662 cfgerr++;
7663 continue;
7664 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007665 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7666
7667 if (!LIST_ISEMPTY(&rule->be.expr)) {
7668 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7669 rule->dynamic = 1;
7670 free(pxname);
7671 continue;
7672 }
7673 /* simple string: free the expression and fall back to static rule */
7674 free(node->arg);
7675 free(node);
7676 }
7677
7678 rule->dynamic = 0;
7679 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007680
Willy Tarreauafb39922015-05-26 12:04:09 +02007681 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007682 if (!target) {
7683 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7684 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007685 cfgerr++;
7686 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007687 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7688 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007689 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007690 } else if (target->mode != curproxy->mode &&
7691 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7692
7693 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7694 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7695 curproxy->conf.file, curproxy->conf.line,
7696 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7697 target->conf.file, target->conf.line);
7698 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007699 } else {
7700 free((void *)rule->be.name);
7701 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007702 /* For each target of switching rules, we update
7703 * their tot_fe_maxconn, except if a previous rule point
7704 * on the same backend or on the default backend */
7705 if (rule->be.backend != curproxy->defbe.be) {
7706 struct switching_rule *swrule;
7707
7708 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7709 if (rule == swrule) {
7710 target->tot_fe_maxconn += curproxy->maxconn;
7711 break;
7712 }
7713 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7714 /* there is multiple ref of this backend */
7715 break;
7716 }
7717 }
7718 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007719 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007720 }
7721
Willy Tarreau64ab6072014-09-16 12:17:36 +02007722 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007723 list_for_each_entry(srule, &curproxy->server_rules, list) {
7724 struct server *target = findserver(curproxy, srule->srv.name);
7725
7726 if (!target) {
7727 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7728 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7729 cfgerr++;
7730 continue;
7731 }
7732 free((void *)srule->srv.name);
7733 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007734 }
7735
Emeric Brunb982a3d2010-01-04 15:45:53 +01007736 /* find the target table for 'stick' rules */
7737 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7738 struct proxy *target;
7739
Emeric Brun1d33b292010-01-04 15:47:17 +01007740 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7741 if (mrule->flags & STK_IS_STORE)
7742 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7743
Emeric Brunb982a3d2010-01-04 15:45:53 +01007744 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007745 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007746 else
7747 target = curproxy;
7748
7749 if (!target) {
7750 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7751 curproxy->id, mrule->table.name);
7752 cfgerr++;
7753 }
7754 else if (target->table.size == 0) {
7755 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7756 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7757 cfgerr++;
7758 }
Willy Tarreau12785782012-04-27 21:37:17 +02007759 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7760 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007761 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7762 cfgerr++;
7763 }
7764 else {
7765 free((void *)mrule->table.name);
7766 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007767 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007768 }
7769 }
7770
7771 /* find the target table for 'store response' rules */
7772 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7773 struct proxy *target;
7774
Emeric Brun1d33b292010-01-04 15:47:17 +01007775 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7776
Emeric Brunb982a3d2010-01-04 15:45:53 +01007777 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007778 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007779 else
7780 target = curproxy;
7781
7782 if (!target) {
7783 Alert("Proxy '%s': unable to find store table '%s'.\n",
7784 curproxy->id, mrule->table.name);
7785 cfgerr++;
7786 }
7787 else if (target->table.size == 0) {
7788 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7789 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7790 cfgerr++;
7791 }
Willy Tarreau12785782012-04-27 21:37:17 +02007792 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7793 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007794 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7795 cfgerr++;
7796 }
7797 else {
7798 free((void *)mrule->table.name);
7799 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007800 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007801 }
7802 }
7803
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007804 /* find the target table for 'tcp-request' layer 4 rules */
7805 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7806 struct proxy *target;
7807
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007808 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007809 continue;
7810
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007811 if (trule->arg.trk_ctr.table.n)
7812 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007813 else
7814 target = curproxy;
7815
7816 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007817 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007818 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007819 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007820 cfgerr++;
7821 }
7822 else if (target->table.size == 0) {
7823 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007824 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007825 cfgerr++;
7826 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007827 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007828 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007829 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007830 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007831 cfgerr++;
7832 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007833 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007834 free(trule->arg.trk_ctr.table.n);
7835 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007836 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007837 * to pass a list of counters to track and allocate them right here using
7838 * stktable_alloc_data_type().
7839 */
7840 }
7841 }
7842
Willy Tarreau620408f2016-10-21 16:37:51 +02007843 /* find the target table for 'tcp-request' layer 5 rules */
7844 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7845 struct proxy *target;
7846
7847 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7848 continue;
7849
7850 if (trule->arg.trk_ctr.table.n)
7851 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7852 else
7853 target = curproxy;
7854
7855 if (!target) {
7856 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7857 curproxy->id, trule->arg.trk_ctr.table.n,
7858 tcp_trk_idx(trule->action));
7859 cfgerr++;
7860 }
7861 else if (target->table.size == 0) {
7862 Alert("Proxy '%s': table '%s' used but not configured.\n",
7863 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7864 cfgerr++;
7865 }
7866 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7867 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7868 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7869 tcp_trk_idx(trule->action));
7870 cfgerr++;
7871 }
7872 else {
7873 free(trule->arg.trk_ctr.table.n);
7874 trule->arg.trk_ctr.table.t = &target->table;
7875 /* Note: if we decide to enhance the track-sc syntax, we may be able
7876 * to pass a list of counters to track and allocate them right here using
7877 * stktable_alloc_data_type().
7878 */
7879 }
7880 }
7881
Willy Tarreaud1f96522010-08-03 19:34:32 +02007882 /* find the target table for 'tcp-request' layer 6 rules */
7883 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7884 struct proxy *target;
7885
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007886 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007887 continue;
7888
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007889 if (trule->arg.trk_ctr.table.n)
7890 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007891 else
7892 target = curproxy;
7893
7894 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007895 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007896 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007897 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007898 cfgerr++;
7899 }
7900 else if (target->table.size == 0) {
7901 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007902 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007903 cfgerr++;
7904 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007905 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007906 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007907 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007908 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007909 cfgerr++;
7910 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007911 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007912 free(trule->arg.trk_ctr.table.n);
7913 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007914 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007915 * to pass a list of counters to track and allocate them right here using
7916 * stktable_alloc_data_type().
7917 */
7918 }
7919 }
7920
Baptiste Assmanne9544932015-11-03 23:31:35 +01007921 /* parse http-request capture rules to ensure id really exists */
7922 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7923 if (hrqrule->action != ACT_CUSTOM ||
7924 hrqrule->action_ptr != http_action_req_capture_by_id)
7925 continue;
7926
7927 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7928 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7929 curproxy->id, hrqrule->arg.capid.idx);
7930 cfgerr++;
7931 }
7932 }
7933
7934 /* parse http-response capture rules to ensure id really exists */
7935 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7936 if (hrqrule->action != ACT_CUSTOM ||
7937 hrqrule->action_ptr != http_action_res_capture_by_id)
7938 continue;
7939
7940 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7941 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7942 curproxy->id, hrqrule->arg.capid.idx);
7943 cfgerr++;
7944 }
7945 }
7946
Willy Tarreau09448f72014-06-25 18:12:15 +02007947 /* find the target table for 'http-request' layer 7 rules */
7948 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7949 struct proxy *target;
7950
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007951 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007952 continue;
7953
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007954 if (hrqrule->arg.trk_ctr.table.n)
7955 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007956 else
7957 target = curproxy;
7958
7959 if (!target) {
7960 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007961 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007962 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007963 cfgerr++;
7964 }
7965 else if (target->table.size == 0) {
7966 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007967 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007968 cfgerr++;
7969 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007970 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007971 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007972 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007973 http_trk_idx(hrqrule->action));
7974 cfgerr++;
7975 }
7976 else {
7977 free(hrqrule->arg.trk_ctr.table.n);
7978 hrqrule->arg.trk_ctr.table.t = &target->table;
7979 /* Note: if we decide to enhance the track-sc syntax, we may be able
7980 * to pass a list of counters to track and allocate them right here using
7981 * stktable_alloc_data_type().
7982 */
7983 }
7984 }
7985
7986 /* find the target table for 'http-response' layer 7 rules */
7987 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7988 struct proxy *target;
7989
7990 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7991 continue;
7992
7993 if (hrqrule->arg.trk_ctr.table.n)
7994 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7995 else
7996 target = curproxy;
7997
7998 if (!target) {
7999 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8000 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8001 http_trk_idx(hrqrule->action));
8002 cfgerr++;
8003 }
8004 else if (target->table.size == 0) {
8005 Alert("Proxy '%s': table '%s' used but not configured.\n",
8006 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8007 cfgerr++;
8008 }
8009 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8010 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8011 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8012 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008013 cfgerr++;
8014 }
8015 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008016 free(hrqrule->arg.trk_ctr.table.n);
8017 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008018 /* Note: if we decide to enhance the track-sc syntax, we may be able
8019 * to pass a list of counters to track and allocate them right here using
8020 * stktable_alloc_data_type().
8021 */
8022 }
8023 }
8024
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008025 /* move any "block" rules at the beginning of the http-request rules */
8026 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8027 /* insert block_rules into http_req_rules at the beginning */
8028 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8029 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8030 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8031 curproxy->http_req_rules.n = curproxy->block_rules.n;
8032 LIST_INIT(&curproxy->block_rules);
8033 }
8034
Emeric Brun32da3c42010-09-23 18:39:19 +02008035 if (curproxy->table.peers.name) {
8036 struct peers *curpeers = peers;
8037
8038 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8039 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8040 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008041 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008042 break;
8043 }
8044 }
8045
8046 if (!curpeers) {
8047 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8048 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008049 free((void *)curproxy->table.peers.name);
8050 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008051 cfgerr++;
8052 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008053 else if (curpeers->state == PR_STSTOPPED) {
8054 /* silently disable this peers section */
8055 curproxy->table.peers.p = NULL;
8056 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008057 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008058 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8059 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008060 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008061 cfgerr++;
8062 }
8063 }
8064
Simon Horman9dc49962015-01-30 11:22:59 +09008065
8066 if (curproxy->email_alert.mailers.name) {
8067 struct mailers *curmailers = mailers;
8068
8069 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8070 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8071 free(curproxy->email_alert.mailers.name);
8072 curproxy->email_alert.mailers.m = curmailers;
8073 curmailers->users++;
8074 break;
8075 }
8076 }
8077
8078 if (!curmailers) {
8079 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8080 curproxy->id, curproxy->email_alert.mailers.name);
8081 free_email_alert(curproxy);
8082 cfgerr++;
8083 }
8084 }
8085
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008086 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008087 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008088 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8089 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8090 "proxy", curproxy->id);
8091 cfgerr++;
8092 goto out_uri_auth_compat;
8093 }
8094
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008095 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008096 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008097 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008098 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008099
Willy Tarreau95fa4692010-02-01 13:05:50 +01008100 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8101 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008102
8103 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008104 uri_auth_compat_req[i++] = "realm";
8105 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8106 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008107
Willy Tarreau95fa4692010-02-01 13:05:50 +01008108 uri_auth_compat_req[i++] = "unless";
8109 uri_auth_compat_req[i++] = "{";
8110 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8111 uri_auth_compat_req[i++] = "}";
8112 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008113
Willy Tarreauff011f22011-01-06 17:51:27 +01008114 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8115 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008116 cfgerr++;
8117 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008118 }
8119
Willy Tarreauff011f22011-01-06 17:51:27 +01008120 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008121
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008122 if (curproxy->uri_auth->auth_realm) {
8123 free(curproxy->uri_auth->auth_realm);
8124 curproxy->uri_auth->auth_realm = NULL;
8125 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008126
8127 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008128 }
8129out_uri_auth_compat:
8130
Dragan Dosen43885c72015-10-01 13:18:13 +02008131 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008132 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008133 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8134 if (!curproxy->conf.logformat_sd_string) {
8135 /* set the default logformat_sd_string */
8136 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8137 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008138 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008139 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008140 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008141
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008142 /* compile the log format */
8143 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008144 if (curproxy->conf.logformat_string != default_http_log_format &&
8145 curproxy->conf.logformat_string != default_tcp_log_format &&
8146 curproxy->conf.logformat_string != clf_http_log_format)
8147 free(curproxy->conf.logformat_string);
8148 curproxy->conf.logformat_string = NULL;
8149 free(curproxy->conf.lfs_file);
8150 curproxy->conf.lfs_file = NULL;
8151 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008152
8153 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8154 free(curproxy->conf.logformat_sd_string);
8155 curproxy->conf.logformat_sd_string = NULL;
8156 free(curproxy->conf.lfsd_file);
8157 curproxy->conf.lfsd_file = NULL;
8158 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008159 }
8160
Willy Tarreau62a61232013-04-12 18:13:46 +02008161 if (curproxy->conf.logformat_string) {
8162 curproxy->conf.args.ctx = ARGC_LOG;
8163 curproxy->conf.args.file = curproxy->conf.lfs_file;
8164 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008165 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008166 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008167 SMP_VAL_FE_LOG_END, &err)) {
8168 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8169 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8170 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008171 cfgerr++;
8172 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008173 curproxy->conf.args.file = NULL;
8174 curproxy->conf.args.line = 0;
8175 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008176
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008177 if (curproxy->conf.logformat_sd_string) {
8178 curproxy->conf.args.ctx = ARGC_LOGSD;
8179 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8180 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008181 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008182 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 +01008183 SMP_VAL_FE_LOG_END, &err)) {
8184 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8185 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8186 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008187 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008188 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8189 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8190 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8191 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008192 cfgerr++;
8193 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008194 curproxy->conf.args.file = NULL;
8195 curproxy->conf.args.line = 0;
8196 }
8197
Willy Tarreau62a61232013-04-12 18:13:46 +02008198 if (curproxy->conf.uniqueid_format_string) {
8199 curproxy->conf.args.ctx = ARGC_UIF;
8200 curproxy->conf.args.file = curproxy->conf.uif_file;
8201 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008202 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008203 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 +01008204 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8205 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8206 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8207 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008208 cfgerr++;
8209 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008210 curproxy->conf.args.file = NULL;
8211 curproxy->conf.args.line = 0;
8212 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008213
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008214 /* only now we can check if some args remain unresolved.
8215 * This must be done after the users and groups resolution.
8216 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008217 cfgerr += smp_resolve_args(curproxy);
8218 if (!cfgerr)
8219 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008220
Willy Tarreau2738a142006-07-08 17:28:09 +02008221 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008222 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008223 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008224 (!curproxy->timeout.connect ||
8225 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008226 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008227 " | While not properly invalid, you will certainly encounter various problems\n"
8228 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008229 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008230 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008231 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008232 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008233
Willy Tarreau1fa31262007-12-03 00:36:16 +01008234 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8235 * We must still support older configurations, so let's find out whether those
8236 * parameters have been set or must be copied from contimeouts.
8237 */
8238 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008239 if (!curproxy->timeout.tarpit ||
8240 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008241 /* tarpit timeout not set. We search in the following order:
8242 * default.tarpit, curr.connect, default.connect.
8243 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008244 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008245 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008246 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008247 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008248 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008249 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008250 }
8251 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008252 (!curproxy->timeout.queue ||
8253 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008254 /* queue timeout not set. We search in the following order:
8255 * default.queue, curr.connect, default.connect.
8256 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008257 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008258 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008259 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008260 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008261 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008262 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008263 }
8264 }
8265
Willy Tarreau1620ec32011-08-06 17:05:02 +02008266 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008267 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008268 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008269 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008270 }
8271
Willy Tarreau215663d2014-06-13 18:30:23 +02008272 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8273 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8274 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8275 proxy_type_str(curproxy), curproxy->id);
8276 err_code |= ERR_WARN;
8277 }
8278
Willy Tarreau193b8c62012-11-22 00:17:38 +01008279 /* ensure that cookie capture length is not too large */
8280 if (curproxy->capture_len >= global.tune.cookie_len) {
8281 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8282 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8283 err_code |= ERR_WARN;
8284 curproxy->capture_len = global.tune.cookie_len - 1;
8285 }
8286
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008287 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008288 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008289 curproxy->req_cap_pool = create_pool("ptrcap",
8290 curproxy->nb_req_cap * sizeof(char *),
8291 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008292 }
8293
8294 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008295 curproxy->rsp_cap_pool = create_pool("ptrcap",
8296 curproxy->nb_rsp_cap * sizeof(char *),
8297 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008298 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008299
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008300 switch (curproxy->load_server_state_from_file) {
8301 case PR_SRV_STATE_FILE_UNSPEC:
8302 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8303 break;
8304 case PR_SRV_STATE_FILE_GLOBAL:
8305 if (!global.server_state_file) {
8306 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",
8307 curproxy->id);
8308 err_code |= ERR_WARN;
8309 }
8310 break;
8311 }
8312
Willy Tarreaubaaee002006-06-26 02:48:02 +02008313 /* first, we will invert the servers list order */
8314 newsrv = NULL;
8315 while (curproxy->srv) {
8316 struct server *next;
8317
8318 next = curproxy->srv->next;
8319 curproxy->srv->next = newsrv;
8320 newsrv = curproxy->srv;
8321 if (!next)
8322 break;
8323 curproxy->srv = next;
8324 }
8325
Willy Tarreau17edc812014-01-03 12:14:34 +01008326 /* Check that no server name conflicts. This causes trouble in the stats.
8327 * We only emit a warning for the first conflict affecting each server,
8328 * in order to avoid combinatory explosion if all servers have the same
8329 * name. We do that only for servers which do not have an explicit ID,
8330 * because these IDs were made also for distinguishing them and we don't
8331 * want to annoy people who correctly manage them.
8332 */
8333 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8334 struct server *other_srv;
8335
8336 if (newsrv->puid)
8337 continue;
8338
8339 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8340 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8341 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8342 newsrv->conf.file, newsrv->conf.line,
8343 proxy_type_str(curproxy), curproxy->id,
8344 newsrv->id, other_srv->conf.line);
8345 break;
8346 }
8347 }
8348 }
8349
Willy Tarreaudd701652010-05-25 23:03:02 +02008350 /* assign automatic UIDs to servers which don't have one yet */
8351 next_id = 1;
8352 newsrv = curproxy->srv;
8353 while (newsrv != NULL) {
8354 if (!newsrv->puid) {
8355 /* server ID not set, use automatic numbering with first
8356 * spare entry starting with next_svid.
8357 */
8358 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8359 newsrv->conf.id.key = newsrv->puid = next_id;
8360 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8361 }
8362 next_id++;
8363 newsrv = newsrv->next;
8364 }
8365
Willy Tarreau20697042007-11-15 23:26:18 +01008366 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008367 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008368
Willy Tarreau62c3be22012-01-20 13:12:32 +01008369 /*
8370 * If this server supports a maxconn parameter, it needs a dedicated
8371 * tasks to fill the emptied slots when a connection leaves.
8372 * Also, resolve deferred tracking dependency if needed.
8373 */
8374 newsrv = curproxy->srv;
8375 while (newsrv != NULL) {
8376 if (newsrv->minconn > newsrv->maxconn) {
8377 /* Only 'minconn' was specified, or it was higher than or equal
8378 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8379 * this will avoid further useless expensive computations.
8380 */
8381 newsrv->maxconn = newsrv->minconn;
8382 } else if (newsrv->maxconn && !newsrv->minconn) {
8383 /* minconn was not specified, so we set it to maxconn */
8384 newsrv->minconn = newsrv->maxconn;
8385 }
8386
Willy Tarreau17d45382016-12-22 21:16:08 +01008387 /* this will also properly set the transport layer for prod and checks */
8388 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8389 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8390 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8391 }
Emeric Brun94324a42012-10-11 14:00:19 +02008392
Willy Tarreau2f075e92013-12-03 11:11:34 +01008393 /* set the check type on the server */
8394 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8395
Willy Tarreau62c3be22012-01-20 13:12:32 +01008396 if (newsrv->trackit) {
8397 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008398 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008399 char *pname, *sname;
8400
8401 pname = newsrv->trackit;
8402 sname = strrchr(pname, '/');
8403
8404 if (sname)
8405 *sname++ = '\0';
8406 else {
8407 sname = pname;
8408 pname = NULL;
8409 }
8410
8411 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008412 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008413 if (!px) {
8414 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8415 proxy_type_str(curproxy), curproxy->id,
8416 newsrv->id, pname);
8417 cfgerr++;
8418 goto next_srv;
8419 }
8420 } else
8421 px = curproxy;
8422
8423 srv = findserver(px, sname);
8424 if (!srv) {
8425 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8426 proxy_type_str(curproxy), curproxy->id,
8427 newsrv->id, sname);
8428 cfgerr++;
8429 goto next_srv;
8430 }
8431
Willy Tarreau32091232014-05-16 13:52:00 +02008432 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8433 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8434 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008435 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008436 "tracking as it does not have any check nor agent enabled.\n",
8437 proxy_type_str(curproxy), curproxy->id,
8438 newsrv->id, px->id, srv->id);
8439 cfgerr++;
8440 goto next_srv;
8441 }
8442
8443 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8444
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008445 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008446 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8447 "belongs to a tracking chain looping back to %s/%s.\n",
8448 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008449 newsrv->id, px->id, srv->id, px->id,
8450 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008451 cfgerr++;
8452 goto next_srv;
8453 }
8454
8455 if (curproxy != px &&
8456 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8457 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8458 "tracking: disable-on-404 option inconsistency.\n",
8459 proxy_type_str(curproxy), curproxy->id,
8460 newsrv->id, px->id, srv->id);
8461 cfgerr++;
8462 goto next_srv;
8463 }
8464
Willy Tarreau62c3be22012-01-20 13:12:32 +01008465 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008466 newsrv->tracknext = srv->trackers;
8467 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008468
8469 free(newsrv->trackit);
8470 newsrv->trackit = NULL;
8471 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008472
8473 /*
8474 * resolve server's resolvers name and update the resolvers pointer
8475 * accordingly
8476 */
8477 if (newsrv->resolvers_id) {
8478 struct dns_resolvers *curr_resolvers;
8479 int found;
8480
8481 found = 0;
8482 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8483 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8484 found = 1;
8485 break;
8486 }
8487 }
8488
8489 if (!found) {
8490 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8491 proxy_type_str(curproxy), curproxy->id,
8492 newsrv->id, newsrv->resolvers_id);
8493 cfgerr++;
8494 } else {
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008495 if (newsrv->resolution)
8496 newsrv->resolution->resolvers = curr_resolvers;
8497 }
8498 }
8499 else {
8500 /* if no resolvers section associated to this server
8501 * we can clean up the associated resolution structure
8502 */
8503 if (newsrv->resolution) {
8504 free(newsrv->resolution->hostname_dn);
8505 newsrv->resolution->hostname_dn = NULL;
8506 free(newsrv->resolution);
8507 newsrv->resolution = NULL;
8508 }
8509 }
8510
Willy Tarreau62c3be22012-01-20 13:12:32 +01008511 next_srv:
8512 newsrv = newsrv->next;
8513 }
8514
Olivier Houchard4e694042017-03-14 20:01:29 +01008515 /*
8516 * Try to generate dynamic cookies for servers now.
8517 * It couldn't be done earlier, since at the time we parsed
8518 * the server line, we may not have known yet that we
8519 * should use dynamic cookies, or the secret key may not
8520 * have been provided yet.
8521 */
8522 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8523 newsrv = curproxy->srv;
8524 while (newsrv != NULL) {
8525 srv_set_dyncookie(newsrv);
8526 newsrv = newsrv->next;
8527 }
8528
8529 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008530 /* We have to initialize the server lookup mechanism depending
8531 * on what LB algorithm was choosen.
8532 */
8533
8534 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8535 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8536 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008537 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8538 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8539 init_server_map(curproxy);
8540 } else {
8541 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8542 fwrr_init_server_groups(curproxy);
8543 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008544 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008545
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008546 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008547 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8548 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8549 fwlc_init_server_tree(curproxy);
8550 } else {
8551 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8552 fas_init_server_tree(curproxy);
8553 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008554 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008555
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008556 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008557 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8558 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8559 chash_init_server_tree(curproxy);
8560 } else {
8561 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8562 init_server_map(curproxy);
8563 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008564 break;
8565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008566
8567 if (curproxy->options & PR_O_LOGASAP)
8568 curproxy->to_log &= ~LW_BYTES;
8569
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008570 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008571 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8572 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008573 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8574 proxy_type_str(curproxy), curproxy->id);
8575 err_code |= ERR_WARN;
8576 }
8577
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008578 if (curproxy->mode != PR_MODE_HTTP) {
8579 int optnum;
8580
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008581 if (curproxy->uri_auth) {
8582 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8583 proxy_type_str(curproxy), curproxy->id);
8584 err_code |= ERR_WARN;
8585 curproxy->uri_auth = NULL;
8586 }
8587
Willy Tarreaude7dc882017-03-10 11:49:21 +01008588 if (curproxy->capture_name) {
8589 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8590 proxy_type_str(curproxy), curproxy->id);
8591 err_code |= ERR_WARN;
8592 }
8593
8594 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8595 Warning("config : 'http-request' 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->http_res_rules)) {
8601 Warning("config : 'http-response' 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->block_rules)) {
8607 Warning("config : 'block' 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
8612 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8613 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8614 proxy_type_str(curproxy), curproxy->id);
8615 err_code |= ERR_WARN;
8616 }
8617
Willy Tarreau87cf5142011-08-19 22:57:24 +02008618 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008619 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8620 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8621 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008622 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008623 }
8624
8625 if (curproxy->options & PR_O_ORGTO) {
8626 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8627 "originalto", proxy_type_str(curproxy), curproxy->id);
8628 err_code |= ERR_WARN;
8629 curproxy->options &= ~PR_O_ORGTO;
8630 }
8631
8632 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8633 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8634 (curproxy->cap & cfg_opts[optnum].cap) &&
8635 (curproxy->options & cfg_opts[optnum].val)) {
8636 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8637 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8638 err_code |= ERR_WARN;
8639 curproxy->options &= ~cfg_opts[optnum].val;
8640 }
8641 }
8642
8643 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8644 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8645 (curproxy->cap & cfg_opts2[optnum].cap) &&
8646 (curproxy->options2 & cfg_opts2[optnum].val)) {
8647 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8648 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8649 err_code |= ERR_WARN;
8650 curproxy->options2 &= ~cfg_opts2[optnum].val;
8651 }
8652 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008653
Willy Tarreau29fbe512015-08-20 19:35:14 +02008654#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008655 if (curproxy->conn_src.bind_hdr_occ) {
8656 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008657 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008658 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008659 err_code |= ERR_WARN;
8660 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008661#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008662 }
8663
Willy Tarreaubaaee002006-06-26 02:48:02 +02008664 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008665 * ensure that we're not cross-dressing a TCP server into HTTP.
8666 */
8667 newsrv = curproxy->srv;
8668 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008669 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008670 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8671 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008672 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008673 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008674
Willy Tarreau0cec3312011-10-31 13:49:26 +01008675 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8676 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8677 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8678 err_code |= ERR_WARN;
8679 }
8680
Willy Tarreauc93cd162014-05-13 15:54:22 +02008681 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008682 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8683 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8684 err_code |= ERR_WARN;
8685 }
8686
Willy Tarreau29fbe512015-08-20 19:35:14 +02008687#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008688 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8689 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008690 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 +01008691 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008692 err_code |= ERR_WARN;
8693 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008694#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008695
8696 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8697 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8698 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8699 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8700 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8701 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",
8702 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8703 err_code |= ERR_WARN;
8704 }
8705
8706
8707 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8708 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",
8709 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8710 err_code |= ERR_WARN;
8711 }
8712 }
8713
Willy Tarreau21d2af32008-02-14 20:25:24 +01008714 newsrv = newsrv->next;
8715 }
8716
Willy Tarreaue42bd962014-09-16 16:21:19 +02008717 /* check if we have a frontend with "tcp-request content" looking at L7
8718 * with no inspect-delay
8719 */
8720 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8721 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008722 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008723 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008724 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008725 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008726 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008727 break;
8728 }
8729
8730 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8731 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8732 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8733 " This means that these rules will randomly find their contents. This can be fixed by"
8734 " setting the tcp-request inspect-delay.\n",
8735 proxy_type_str(curproxy), curproxy->id);
8736 err_code |= ERR_WARN;
8737 }
8738 }
8739
Christopher Fauletd7c91962015-04-30 11:48:27 +02008740 /* Check filter configuration, if any */
8741 cfgerr += flt_check(curproxy);
8742
Willy Tarreauc1a21672009-08-16 22:37:44 +02008743 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008744 if (!curproxy->accept)
8745 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008746
Willy Tarreauc1a21672009-08-16 22:37:44 +02008747 if (curproxy->tcp_req.inspect_delay ||
8748 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008749 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008750
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008751 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008752 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008753 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008754 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008755
8756 /* both TCP and HTTP must check switching rules */
8757 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008758
8759 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008760 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008761 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8762 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 +01008763 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008764 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8765 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008766 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008767 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008768 }
8769
8770 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008771 if (curproxy->tcp_req.inspect_delay ||
8772 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8773 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8774
Emeric Brun97679e72010-09-23 17:56:44 +02008775 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8776 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8777
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008778 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008779 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008780 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008781 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008782
8783 /* If the backend does requires RDP cookie persistence, we have to
8784 * enable the corresponding analyser.
8785 */
8786 if (curproxy->options2 & PR_O2_RDPC_PRST)
8787 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008788
8789 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008790 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008791 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8792 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 +01008793 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008794 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8795 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008796 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008797 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008798 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008799 }
8800
8801 /***********************************************************/
8802 /* At this point, target names have already been resolved. */
8803 /***********************************************************/
8804
8805 /* Check multi-process mode compatibility */
8806
8807 if (global.nbproc > 1 && global.stats_fe) {
8808 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8809 unsigned long mask;
8810
8811 mask = nbits(global.nbproc);
8812 if (global.stats_fe->bind_proc)
8813 mask &= global.stats_fe->bind_proc;
8814
8815 if (bind_conf->bind_proc)
8816 mask &= bind_conf->bind_proc;
8817
8818 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008819 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008820 break;
8821 }
8822 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8823 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");
8824 }
8825 }
8826
8827 /* Make each frontend inherit bind-process from its listeners when not specified. */
8828 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8829 if (curproxy->bind_proc)
8830 continue;
8831
8832 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8833 unsigned long mask;
8834
Willy Tarreaue428b082015-05-04 21:57:58 +02008835 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008836 curproxy->bind_proc |= mask;
8837 }
8838
8839 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008840 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008841 }
8842
8843 if (global.stats_fe) {
8844 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8845 unsigned long mask;
8846
Cyril Bonté06181952016-02-24 00:14:54 +01008847 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008848 global.stats_fe->bind_proc |= mask;
8849 }
8850 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008851 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008852 }
8853
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008854 /* propagate bindings from frontends to backends. Don't do it if there
8855 * are any fatal errors as we must not call it with unresolved proxies.
8856 */
8857 if (!cfgerr) {
8858 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8859 if (curproxy->cap & PR_CAP_FE)
8860 propagate_processes(curproxy, NULL);
8861 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008862 }
8863
8864 /* Bind each unbound backend to all processes when not specified. */
8865 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8866 if (curproxy->bind_proc)
8867 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008868 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008869 }
8870
8871 /*******************************************************/
8872 /* At this step, all proxies have a non-null bind_proc */
8873 /*******************************************************/
8874
8875 /* perform the final checks before creating tasks */
8876
8877 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8878 struct listener *listener;
8879 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008880
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008881 /* Configure SSL for each bind line.
8882 * Note: if configuration fails at some point, the ->ctx member
8883 * remains NULL so that listeners can later detach.
8884 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008885 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008886 if (bind_conf->xprt->prepare_bind_conf &&
8887 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008888 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008889 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008890
Willy Tarreaue6b98942007-10-29 01:09:36 +01008891 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008892 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008893 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008894 int nbproc;
8895
8896 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008897 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008898 nbits(global.nbproc));
8899
8900 if (!nbproc) /* no intersection between listener and frontend */
8901 nbproc = 1;
8902
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008903 if (!listener->luid) {
8904 /* listener ID not set, use automatic numbering with first
8905 * spare entry starting with next_luid.
8906 */
8907 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8908 listener->conf.id.key = listener->luid = next_id;
8909 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008910 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008911 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008912
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008913 /* enable separate counters */
8914 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008915 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008916 if (!listener->name)
8917 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008918 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008919
Willy Tarreaue6b98942007-10-29 01:09:36 +01008920 if (curproxy->options & PR_O_TCP_NOLING)
8921 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008922 if (!listener->maxconn)
8923 listener->maxconn = curproxy->maxconn;
8924 if (!listener->backlog)
8925 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008926 if (!listener->maxaccept)
8927 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8928
8929 /* we want to have an optimal behaviour on single process mode to
8930 * maximize the work at once, but in multi-process we want to keep
8931 * some fairness between processes, so we target half of the max
8932 * number of events to be balanced over all the processes the proxy
8933 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8934 * used to disable the limit.
8935 */
8936 if (listener->maxaccept > 0) {
8937 if (nbproc > 1)
8938 listener->maxaccept = (listener->maxaccept + 1) / 2;
8939 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8940 }
8941
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008942 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008943 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008944 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008945 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008946
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008947 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008948 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008949
Willy Tarreau620408f2016-10-21 16:37:51 +02008950 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8951 listener->options |= LI_O_TCP_L5_RULES;
8952
Willy Tarreaude3041d2010-05-31 10:56:17 +02008953 if (curproxy->mon_mask.s_addr)
8954 listener->options |= LI_O_CHK_MONNET;
8955
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008956 /* smart accept mode is automatic in HTTP mode */
8957 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008958 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008959 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8960 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008961 }
8962
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008963 /* Release unused SSL configs */
8964 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008965 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8966 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008967 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008968
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008969 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008970 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008971 int count, maxproc = 0;
8972
8973 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008974 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008975 if (count > maxproc)
8976 maxproc = count;
8977 }
8978 /* backends have 0, frontends have 1 or more */
8979 if (maxproc != 1)
8980 Warning("Proxy '%s': in multi-process mode, stats will be"
8981 " limited to process assigned to the current request.\n",
8982 curproxy->id);
8983
Willy Tarreau102df612014-05-07 23:56:38 +02008984 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8985 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8986 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008987 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008988 }
Willy Tarreau102df612014-05-07 23:56:38 +02008989 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8990 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8991 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008992 }
8993 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008994
8995 /* create the task associated with the proxy */
8996 curproxy->task = task_new();
8997 if (curproxy->task) {
8998 curproxy->task->context = curproxy;
8999 curproxy->task->process = manage_proxy;
9000 /* no need to queue, it will be done automatically if some
9001 * listener gets limited.
9002 */
9003 curproxy->task->expire = TICK_ETERNITY;
9004 } else {
9005 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9006 curproxy->id);
9007 cfgerr++;
9008 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009009 }
9010
Willy Tarreaufbb78422011-06-05 15:38:35 +02009011 /* automatically compute fullconn if not set. We must not do it in the
9012 * loop above because cross-references are not yet fully resolved.
9013 */
9014 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9015 /* If <fullconn> is not set, let's set it to 10% of the sum of
9016 * the possible incoming frontend's maxconns.
9017 */
9018 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009019 /* we have the sum of the maxconns in <total>. We only
9020 * keep 10% of that sum to set the default fullconn, with
9021 * a hard minimum of 1 (to avoid a divide by zero).
9022 */
Emeric Brun3f783572017-01-12 11:21:28 +01009023 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009024 if (!curproxy->fullconn)
9025 curproxy->fullconn = 1;
9026 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009027 }
9028
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009029 /*
9030 * Recount currently required checks.
9031 */
9032
9033 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9034 int optnum;
9035
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009036 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9037 if (curproxy->options & cfg_opts[optnum].val)
9038 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009039
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009040 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9041 if (curproxy->options2 & cfg_opts2[optnum].val)
9042 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009043 }
9044
Willy Tarreau0fca4832015-05-01 19:12:05 +02009045 /* compute the required process bindings for the peers */
9046 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9047 if (curproxy->table.peers.p)
9048 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9049
Willy Tarreau122541c2011-09-07 21:24:49 +02009050 if (peers) {
9051 struct peers *curpeers = peers, **last;
9052 struct peer *p, *pb;
9053
Willy Tarreau1e273012015-05-01 19:15:17 +02009054 /* Remove all peers sections which don't have a valid listener,
9055 * which are not used by any table, or which are bound to more
9056 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009057 */
9058 last = &peers;
9059 while (*last) {
9060 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009061
9062 if (curpeers->state == PR_STSTOPPED) {
9063 /* the "disabled" keyword was present */
9064 if (curpeers->peers_fe)
9065 stop_proxy(curpeers->peers_fe);
9066 curpeers->peers_fe = NULL;
9067 }
9068 else if (!curpeers->peers_fe) {
9069 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9070 curpeers->id, localpeer);
9071 }
David Carliere6c39412015-07-02 07:00:17 +00009072 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009073 /* either it's totally stopped or too much used */
9074 if (curpeers->peers_fe->bind_proc) {
9075 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009076 "running in different processes (%d different ones). "
9077 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009078 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009079 cfgerr++;
9080 }
9081 stop_proxy(curpeers->peers_fe);
9082 curpeers->peers_fe = NULL;
9083 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009084 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009085 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009086 last = &curpeers->next;
9087 continue;
9088 }
9089
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009090 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009091 p = curpeers->remote;
9092 while (p) {
9093 pb = p->next;
9094 free(p->id);
9095 free(p);
9096 p = pb;
9097 }
9098
9099 /* Destroy and unlink this curpeers section.
9100 * Note: curpeers is backed up into *last.
9101 */
9102 free(curpeers->id);
9103 curpeers = curpeers->next;
9104 free(*last);
9105 *last = curpeers;
9106 }
9107 }
9108
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009109 /* initialize stick-tables on backend capable proxies. This must not
9110 * be done earlier because the data size may be discovered while parsing
9111 * other proxies.
9112 */
9113 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9114 if (curproxy->state == PR_STSTOPPED)
9115 continue;
9116
9117 if (!stktable_init(&curproxy->table)) {
9118 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9119 cfgerr++;
9120 }
9121 }
9122
Simon Horman0d16a402015-01-30 11:22:58 +09009123 if (mailers) {
9124 struct mailers *curmailers = mailers, **last;
9125 struct mailer *m, *mb;
9126
9127 /* Remove all mailers sections which don't have a valid listener.
9128 * This can happen when a mailers section is never referenced.
9129 */
9130 last = &mailers;
9131 while (*last) {
9132 curmailers = *last;
9133 if (curmailers->users) {
9134 last = &curmailers->next;
9135 continue;
9136 }
9137
9138 Warning("Removing incomplete section 'mailers %s'.\n",
9139 curmailers->id);
9140
9141 m = curmailers->mailer_list;
9142 while (m) {
9143 mb = m->next;
9144 free(m->id);
9145 free(m);
9146 m = mb;
9147 }
9148
9149 /* Destroy and unlink this curmailers section.
9150 * Note: curmailers is backed up into *last.
9151 */
9152 free(curmailers->id);
9153 curmailers = curmailers->next;
9154 free(*last);
9155 *last = curmailers;
9156 }
9157 }
9158
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009159 /* Update server_state_file_name to backend name if backend is supposed to use
9160 * a server-state file locally defined and none has been provided */
9161 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9162 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9163 curproxy->server_state_file_name == NULL)
9164 curproxy->server_state_file_name = strdup(curproxy->id);
9165 }
9166
Willy Tarreau34eb6712011-10-24 18:15:04 +02009167 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009168 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009169 MEM_F_SHARED);
9170
Willy Tarreaubb925012009-07-23 13:36:36 +02009171 if (cfgerr > 0)
9172 err_code |= ERR_ALERT | ERR_FATAL;
9173 out:
9174 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009175}
9176
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009177/*
9178 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9179 * parsing sessions.
9180 */
9181void cfg_register_keywords(struct cfg_kw_list *kwl)
9182{
9183 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9184}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009185
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009186/*
9187 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9188 */
9189void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9190{
9191 LIST_DEL(&kwl->list);
9192 LIST_INIT(&kwl->list);
9193}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009194
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009195/* this function register new section in the haproxy configuration file.
9196 * <section_name> is the name of this new section and <section_parser>
9197 * is the called parser. If two section declaration have the same name,
9198 * only the first declared is used.
9199 */
9200int cfg_register_section(char *section_name,
9201 int (*section_parser)(const char *, int, char **, int))
9202{
9203 struct cfg_section *cs;
9204
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009205 list_for_each_entry(cs, &sections, list) {
9206 if (strcmp(cs->section_name, section_name) == 0) {
9207 Alert("register section '%s': already registered.\n", section_name);
9208 return 0;
9209 }
9210 }
9211
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009212 cs = calloc(1, sizeof(*cs));
9213 if (!cs) {
9214 Alert("register section '%s': out of memory.\n", section_name);
9215 return 0;
9216 }
9217
9218 cs->section_name = section_name;
9219 cs->section_parser = section_parser;
9220
9221 LIST_ADDQ(&sections, &cs->list);
9222
9223 return 1;
9224}
9225
Willy Tarreaubaaee002006-06-26 02:48:02 +02009226/*
David Carlier845efb52015-09-25 11:49:18 +01009227 * free all config section entries
9228 */
9229void cfg_unregister_sections(void)
9230{
9231 struct cfg_section *cs, *ics;
9232
9233 list_for_each_entry_safe(cs, ics, &sections, list) {
9234 LIST_DEL(&cs->list);
9235 free(cs);
9236 }
9237}
9238
Christopher Faulet7110b402016-10-26 11:09:44 +02009239void cfg_backup_sections(struct list *backup_sections)
9240{
9241 struct cfg_section *cs, *ics;
9242
9243 list_for_each_entry_safe(cs, ics, &sections, list) {
9244 LIST_DEL(&cs->list);
9245 LIST_ADDQ(backup_sections, &cs->list);
9246 }
9247}
9248
9249void cfg_restore_sections(struct list *backup_sections)
9250{
9251 struct cfg_section *cs, *ics;
9252
9253 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9254 LIST_DEL(&cs->list);
9255 LIST_ADDQ(&sections, &cs->list);
9256 }
9257}
9258
Willy Tarreau659fbf02016-05-26 17:55:28 +02009259__attribute__((constructor))
9260static void cfgparse_init(void)
9261{
9262 /* Register internal sections */
9263 cfg_register_section("listen", cfg_parse_listen);
9264 cfg_register_section("frontend", cfg_parse_listen);
9265 cfg_register_section("backend", cfg_parse_listen);
9266 cfg_register_section("defaults", cfg_parse_listen);
9267 cfg_register_section("global", cfg_parse_global);
9268 cfg_register_section("userlist", cfg_parse_users);
9269 cfg_register_section("peers", cfg_parse_peers);
9270 cfg_register_section("mailers", cfg_parse_mailers);
9271 cfg_register_section("namespace_list", cfg_parse_netns);
9272 cfg_register_section("resolvers", cfg_parse_resolvers);
9273}
9274
David Carlier845efb52015-09-25 11:49:18 +01009275/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009276 * Local variables:
9277 * c-indent-level: 8
9278 * c-basic-offset: 8
9279 * End:
9280 */