blob: 348b9e886667e80157b6b6a2a8f6dcec6ef7f0e4 [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 */
Willy Tarreau272adea2014-03-31 10:39:59 +02002862 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2863 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2864 if (err_code & ERR_FATAL)
2865 goto out;
2866 }
2867 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002868 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002869 int cur_arg;
2870
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 if (curproxy == &defproxy) {
2872 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002876 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878
Willy Tarreau24709282013-03-10 21:32:12 +01002879 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002880 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002885
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002886 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002887
2888 /* use default settings for unix sockets */
2889 bind_conf->ux.uid = global.unix_bind.ux.uid;
2890 bind_conf->ux.gid = global.unix_bind.ux.gid;
2891 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002892
2893 /* NOTE: the following line might create several listeners if there
2894 * are comma-separated IPs or port ranges. So all further processing
2895 * will have to be applied to all listeners created after last_listen.
2896 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002897 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2898 if (errmsg && *errmsg) {
2899 indent_msg(&errmsg, 2);
2900 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002901 }
2902 else
2903 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2904 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002908
Willy Tarreau4348fad2012-09-20 16:48:07 +02002909 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2910 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002911 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002912 }
2913
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002914 cur_arg = 2;
2915 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002916 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002917 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002918 char *err;
2919
Willy Tarreau26982662012-09-12 23:17:10 +02002920 kw = bind_find_kw(args[cur_arg]);
2921 if (kw) {
2922 char *err = NULL;
2923 int code;
2924
2925 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002926 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2927 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002928 cur_arg += 1 + kw->skip ;
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
2932
Willy Tarreau4348fad2012-09-20 16:48:07 +02002933 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002934 err_code |= code;
2935
2936 if (code) {
2937 if (err && *err) {
2938 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002939 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002940 }
2941 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002942 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2943 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002944 if (code & ERR_FATAL) {
2945 free(err);
2946 cur_arg += 1 + kw->skip;
2947 goto out;
2948 }
2949 }
2950 free(err);
2951 cur_arg += 1 + kw->skip;
2952 continue;
2953 }
2954
Willy Tarreau8638f482012-09-18 18:01:17 +02002955 err = NULL;
2956 if (!bind_dumped) {
2957 bind_dump_kws(&err);
2958 indent_msg(&err, 4);
2959 bind_dumped = 1;
2960 }
2961
2962 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2963 file, linenum, args[0], args[1], args[cur_arg],
2964 err ? " Registered keywords :" : "", err ? err : "");
2965 free(err);
2966
Willy Tarreau93893792009-07-23 13:19:11 +02002967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002969 }
Willy Tarreau93893792009-07-23 13:19:11 +02002970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 }
2972 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002973 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2975 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002979 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002980 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002981
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 /* flush useless bits */
2983 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002986 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002987 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002988 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002989
William Lallemanddf1425a2015-04-28 20:17:49 +02002990 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2991 goto out;
2992
Willy Tarreau1c47f852006-07-09 08:22:27 +02002993 if (!*args[1]) {
2994 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2995 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002998 }
2999
Willy Tarreaua534fea2008-08-03 12:19:50 +02003000 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003001 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003002 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003003 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003004 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3005
Willy Tarreau93893792009-07-23 13:19:11 +02003006 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003009 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3010 goto out;
3011
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3013 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3014 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3015 else {
3016 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 }
3020 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003021 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003022 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003023
3024 if (curproxy == &defproxy) {
3025 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3026 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003029 }
3030
William Lallemanddf1425a2015-04-28 20:17:49 +02003031 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3032 goto out;
3033
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003034 if (!*args[1]) {
3035 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3036 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003039 }
3040
3041 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003042 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003043 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003044
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003045 if (curproxy->uuid <= 0) {
3046 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003047 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003050 }
3051
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003052 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3053 if (node) {
3054 struct proxy *target = container_of(node, struct proxy, conf.id);
3055 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3056 file, linenum, proxy_type_str(curproxy), curproxy->id,
3057 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
3060 }
3061 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003062 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003063 else if (!strcmp(args[0], "description")) {
3064 int i, len=0;
3065 char *d;
3066
Cyril Bonté99ed3272010-01-24 23:29:44 +01003067 if (curproxy == &defproxy) {
3068 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3069 file, linenum, args[0]);
3070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
3072 }
3073
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003074 if (!*args[1]) {
3075 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3076 file, linenum, args[0]);
3077 return -1;
3078 }
3079
Willy Tarreau348acfe2014-04-14 15:00:39 +02003080 for (i = 1; *args[i]; i++)
3081 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003082
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003083 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003084 curproxy->desc = d;
3085
Willy Tarreau348acfe2014-04-14 15:00:39 +02003086 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3087 for (i = 2; *args[i]; i++)
3088 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003089
3090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003092 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 curproxy->state = PR_STSTOPPED;
3095 }
3096 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003097 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 curproxy->state = PR_STNEW;
3100 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003101 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3102 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003103 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003104
3105 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003106 unsigned int low, high;
3107
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003108 if (strcmp(args[cur_arg], "all") == 0) {
3109 set = 0;
3110 break;
3111 }
3112 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003113 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003114 }
3115 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003116 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003117 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003118 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003119 char *dash = strchr(args[cur_arg], '-');
3120
3121 low = high = str2uic(args[cur_arg]);
3122 if (dash)
3123 high = str2uic(dash + 1);
3124
3125 if (high < low) {
3126 unsigned int swap = low;
3127 low = high;
3128 high = swap;
3129 }
3130
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003131 if (low < 1 || high > LONGBITS) {
3132 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3133 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003136 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003137 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003138 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003139 }
3140 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003141 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3142 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003145 }
3146 cur_arg++;
3147 }
3148 curproxy->bind_proc = set;
3149 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003150 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003151 if (curproxy == &defproxy) {
3152 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003155 }
3156
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003157 err = invalid_char(args[1]);
3158 if (err) {
3159 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3160 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003162 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003163 }
3164
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003165 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003166 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3167 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003170 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003171 }
3172 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3173
3174 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3175 err_code |= ERR_WARN;
3176
3177 if (*(args[1]) == 0) {
3178 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3179 file, linenum, args[0]);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183 free(curproxy->dyncookie_key);
3184 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003185 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3187 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188
Willy Tarreau977b8e42006-12-29 14:19:17 +01003189 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003191
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 if (*(args[1]) == 0) {
3193 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003198
Willy Tarreau67402132012-05-31 20:40:20 +02003199 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003200 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003201 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003202 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 curproxy->cookie_name = strdup(args[1]);
3204 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003205
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 cur_arg = 2;
3207 while (*(args[cur_arg])) {
3208 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003209 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003212 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
3214 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003215 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
3217 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003218 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 }
3220 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003221 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003223 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003224 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003227 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003229 else if (!strcmp(args[cur_arg], "httponly")) {
3230 curproxy->ck_opts |= PR_CK_HTTPONLY;
3231 }
3232 else if (!strcmp(args[cur_arg], "secure")) {
3233 curproxy->ck_opts |= PR_CK_SECURE;
3234 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003235 else if (!strcmp(args[cur_arg], "domain")) {
3236 if (!*args[cur_arg + 1]) {
3237 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3238 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003241 }
3242
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003243 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003244 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003245 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3246 " dots nor does not start with a dot."
3247 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003248 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003249 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003250 }
3251
3252 err = invalid_domainchar(args[cur_arg + 1]);
3253 if (err) {
3254 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3255 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003258 }
3259
Willy Tarreau68a897b2009-12-03 23:28:34 +01003260 if (!curproxy->cookie_domain) {
3261 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3262 } else {
3263 /* one domain was already specified, add another one by
3264 * building the string which will be returned along with
3265 * the cookie.
3266 */
3267 char *new_ptr;
3268 int new_len = strlen(curproxy->cookie_domain) +
3269 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3270 new_ptr = malloc(new_len);
3271 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3272 free(curproxy->cookie_domain);
3273 curproxy->cookie_domain = new_ptr;
3274 }
Willy Tarreau31936852010-10-06 16:59:56 +02003275 cur_arg++;
3276 }
3277 else if (!strcmp(args[cur_arg], "maxidle")) {
3278 unsigned int maxidle;
3279 const char *res;
3280
3281 if (!*args[cur_arg + 1]) {
3282 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3283 file, linenum, args[cur_arg]);
3284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
3286 }
3287
3288 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3289 if (res) {
3290 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3291 file, linenum, *res, args[cur_arg]);
3292 err_code |= ERR_ALERT | ERR_FATAL;
3293 goto out;
3294 }
3295 curproxy->cookie_maxidle = maxidle;
3296 cur_arg++;
3297 }
3298 else if (!strcmp(args[cur_arg], "maxlife")) {
3299 unsigned int maxlife;
3300 const char *res;
3301
3302 if (!*args[cur_arg + 1]) {
3303 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3304 file, linenum, args[cur_arg]);
3305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
3307 }
3308
3309 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3310 if (res) {
3311 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3312 file, linenum, *res, args[cur_arg]);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003317 cur_arg++;
3318 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003319 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003320
3321 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3322 err_code |= ERR_WARN;
3323 curproxy->ck_opts |= PR_CK_DYNAMIC;
3324 }
3325
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003327 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 +02003328 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 }
3332 cur_arg++;
3333 }
Willy Tarreau67402132012-05-31 20:40:20 +02003334 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3336 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
3339
Willy Tarreau67402132012-05-31 20:40:20 +02003340 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3342 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003345
Willy Tarreau67402132012-05-31 20:40:20 +02003346 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003347 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3348 file, linenum);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003352 else if (!strcmp(args[0], "email-alert")) {
3353 if (*(args[1]) == 0) {
3354 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3355 file, linenum, args[0]);
3356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
3358 }
3359
3360 if (!strcmp(args[1], "from")) {
3361 if (*(args[1]) == 0) {
3362 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3363 file, linenum, args[1]);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
3367 free(curproxy->email_alert.from);
3368 curproxy->email_alert.from = strdup(args[2]);
3369 }
3370 else if (!strcmp(args[1], "mailers")) {
3371 if (*(args[1]) == 0) {
3372 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3373 file, linenum, args[1]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377 free(curproxy->email_alert.mailers.name);
3378 curproxy->email_alert.mailers.name = strdup(args[2]);
3379 }
3380 else if (!strcmp(args[1], "myhostname")) {
3381 if (*(args[1]) == 0) {
3382 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3383 file, linenum, args[1]);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
3387 free(curproxy->email_alert.myhostname);
3388 curproxy->email_alert.myhostname = strdup(args[2]);
3389 }
Simon Horman64e34162015-02-06 11:11:57 +09003390 else if (!strcmp(args[1], "level")) {
3391 curproxy->email_alert.level = get_log_level(args[2]);
3392 if (curproxy->email_alert.level < 0) {
3393 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3394 file, linenum, args[1], args[2]);
3395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
3397 }
3398 }
Simon Horman9dc49962015-01-30 11:22:59 +09003399 else if (!strcmp(args[1], "to")) {
3400 if (*(args[1]) == 0) {
3401 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3402 file, linenum, args[1]);
3403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
3405 }
3406 free(curproxy->email_alert.to);
3407 curproxy->email_alert.to = strdup(args[2]);
3408 }
3409 else {
3410 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3411 file, linenum, args[1]);
3412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
3414 }
Simon Horman64e34162015-02-06 11:11:57 +09003415 /* Indicate that the email_alert is at least partially configured */
3416 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003417 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003418 else if (!strcmp(args[0], "external-check")) {
3419 if (*(args[1]) == 0) {
3420 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3421 file, linenum, args[0]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425
3426 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003427 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003428 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003429 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003430 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3431 file, linenum, args[1]);
3432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
3434 }
3435 free(curproxy->check_command);
3436 curproxy->check_command = strdup(args[2]);
3437 }
3438 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003439 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003440 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003441 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003442 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3443 file, linenum, args[1]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447 free(curproxy->check_path);
3448 curproxy->check_path = strdup(args[2]);
3449 }
3450 else {
3451 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3452 file, linenum, args[1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003457 else if (!strcmp(args[0], "persist")) { /* persist */
3458 if (*(args[1]) == 0) {
3459 Alert("parsing [%s:%d] : missing persist method.\n",
3460 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003463 }
3464
3465 if (!strncmp(args[1], "rdp-cookie", 10)) {
3466 curproxy->options2 |= PR_O2_RDPC_PRST;
3467
Emeric Brunb982a3d2010-01-04 15:45:53 +01003468 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003469 const char *beg, *end;
3470
3471 beg = args[1] + 11;
3472 end = strchr(beg, ')');
3473
William Lallemanddf1425a2015-04-28 20:17:49 +02003474 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3475 goto out;
3476
Emeric Brun647caf12009-06-30 17:57:00 +02003477 if (!end || end == beg) {
3478 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3479 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003482 }
3483
3484 free(curproxy->rdp_cookie_name);
3485 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3486 curproxy->rdp_cookie_len = end-beg;
3487 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003488 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003489 free(curproxy->rdp_cookie_name);
3490 curproxy->rdp_cookie_name = strdup("msts");
3491 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3492 }
3493 else { /* syntax */
3494 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3495 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003498 }
3499 }
3500 else {
3501 Alert("parsing [%s:%d] : unknown persist method.\n",
3502 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003505 }
3506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003508 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003512 else if (!strcmp(args[0], "load-server-state-from-file")) {
3513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3514 err_code |= ERR_WARN;
3515 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3516 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3517 }
3518 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3519 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3520 }
3521 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3522 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3523 }
3524 else {
3525 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3526 file, linenum, args[0], args[1]);
3527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
3529 }
3530 }
3531 else if (!strcmp(args[0], "server-state-file-name")) {
3532 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3533 err_code |= ERR_WARN;
3534 if (*(args[1]) == 0) {
3535 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3536 file, linenum, args[0]);
3537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
3539 }
3540 else if (!strcmp(args[1], "use-backend-name"))
3541 curproxy->server_state_file_name = strdup(curproxy->id);
3542 else
3543 curproxy->server_state_file_name = strdup(args[1]);
3544 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003546 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003548
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003550 if (curproxy == &defproxy) {
3551 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
3554 }
3555
William Lallemand1a748ae2015-05-19 16:37:23 +02003556 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3557 goto out;
3558
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 if (*(args[4]) == 0) {
3560 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3561 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003565 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 curproxy->capture_name = strdup(args[2]);
3567 curproxy->capture_namelen = strlen(curproxy->capture_name);
3568 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 curproxy->to_log |= LW_COOKIE;
3570 }
3571 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3572 struct cap_hdr *hdr;
3573
3574 if (curproxy == &defproxy) {
3575 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 +02003576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 }
3579
William Lallemand1a748ae2015-05-19 16:37:23 +02003580 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3581 goto out;
3582
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3584 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3585 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 }
3589
Vincent Bernat02779b62016-04-03 13:48:43 +02003590 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 hdr->next = curproxy->req_cap;
3592 hdr->name = strdup(args[3]);
3593 hdr->namelen = strlen(args[3]);
3594 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003595 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 hdr->index = curproxy->nb_req_cap++;
3597 curproxy->req_cap = hdr;
3598 curproxy->to_log |= LW_REQHDR;
3599 }
3600 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3601 struct cap_hdr *hdr;
3602
3603 if (curproxy == &defproxy) {
3604 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 +02003605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 }
3608
William Lallemand1a748ae2015-05-19 16:37:23 +02003609 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3610 goto out;
3611
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3613 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3614 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003618 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 hdr->next = curproxy->rsp_cap;
3620 hdr->name = strdup(args[3]);
3621 hdr->namelen = strlen(args[3]);
3622 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003623 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 hdr->index = curproxy->nb_rsp_cap++;
3625 curproxy->rsp_cap = hdr;
3626 curproxy->to_log |= LW_RSPHDR;
3627 }
3628 else {
3629 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
3634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003638
William Lallemanddf1425a2015-04-28 20:17:49 +02003639 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3640 goto out;
3641
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 if (*(args[1]) == 0) {
3643 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 }
3648 curproxy->conn_retries = atol(args[1]);
3649 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003650 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003651 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003652
3653 if (curproxy == &defproxy) {
3654 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
3657 }
3658
Willy Tarreau20b0de52012-12-24 15:45:22 +01003659 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003660 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003661 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3662 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3663 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3664 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003665 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 +01003666 file, linenum, args[0]);
3667 err_code |= ERR_WARN;
3668 }
3669
Willy Tarreauff011f22011-01-06 17:51:27 +01003670 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003671
Willy Tarreauff011f22011-01-06 17:51:27 +01003672 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003673 err_code |= ERR_ALERT | ERR_ABORT;
3674 goto out;
3675 }
3676
Willy Tarreau5002f572014-04-23 01:32:02 +02003677 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003678 err_code |= warnif_cond_conflicts(rule->cond,
3679 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3680 file, linenum);
3681
Willy Tarreauff011f22011-01-06 17:51:27 +01003682 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003683 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003684 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003685 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003686
3687 if (curproxy == &defproxy) {
3688 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692
3693 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003694 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003695 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3696 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003697 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3698 file, linenum, args[0]);
3699 err_code |= ERR_WARN;
3700 }
3701
3702 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3703
3704 if (!rule) {
3705 err_code |= ERR_ALERT | ERR_ABORT;
3706 goto out;
3707 }
3708
3709 err_code |= warnif_cond_conflicts(rule->cond,
3710 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3711 file, linenum);
3712
3713 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3714 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003715 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3716 /* set the header name and length into the proxy structure */
3717 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3718 err_code |= ERR_WARN;
3719
3720 if (!*args[1]) {
3721 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3722 file, linenum, args[0]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726
3727 /* set the desired header name */
3728 free(curproxy->server_id_hdr_name);
3729 curproxy->server_id_hdr_name = strdup(args[1]);
3730 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3731 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003732 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003733 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003734
Willy Tarreaub099aca2008-10-12 17:26:37 +02003735 if (curproxy == &defproxy) {
3736 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003739 }
3740
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003741 /* emulate "block" using "http-request block". Since these rules are supposed to
3742 * be processed before all http-request rules, we put them into their own list
3743 * and will insert them at the end.
3744 */
3745 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3746 if (!rule) {
3747 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003748 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003749 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003750 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3751 err_code |= warnif_cond_conflicts(rule->cond,
3752 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3753 file, linenum);
3754 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003755
3756 if (!already_warned(WARN_BLOCK_DEPRECATED))
3757 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]);
3758
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003759 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003760 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003761 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003762
Cyril Bonté99ed3272010-01-24 23:29:44 +01003763 if (curproxy == &defproxy) {
3764 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
3767 }
3768
Willy Tarreaube4653b2015-05-28 15:26:58 +02003769 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003770 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3771 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003774 }
3775
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003776 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003777 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003778 err_code |= warnif_cond_conflicts(rule->cond,
3779 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3780 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003781 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003782 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003783 struct switching_rule *rule;
3784
Willy Tarreaub099aca2008-10-12 17:26:37 +02003785 if (curproxy == &defproxy) {
3786 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003789 }
3790
Willy Tarreau55ea7572007-06-17 19:56:27 +02003791 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003793
3794 if (*(args[1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003798 }
3799
Willy Tarreauf51658d2014-04-23 01:21:56 +02003800 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3801 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3802 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3803 file, linenum, errmsg);
3804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
3806 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003807
Willy Tarreauf51658d2014-04-23 01:21:56 +02003808 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003809 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003810 else if (*args[2]) {
3811 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3812 file, linenum, args[2]);
3813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
3815 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003816
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003817 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003818 if (!rule) {
3819 Alert("Out of memory error.\n");
3820 goto out;
3821 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003822 rule->cond = cond;
3823 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003824 rule->line = linenum;
3825 rule->file = strdup(file);
3826 if (!rule->file) {
3827 Alert("Out of memory error.\n");
3828 goto out;
3829 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003830 LIST_INIT(&rule->list);
3831 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3832 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003833 else if (strcmp(args[0], "use-server") == 0) {
3834 struct server_rule *rule;
3835
3836 if (curproxy == &defproxy) {
3837 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840 }
3841
3842 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3843 err_code |= ERR_WARN;
3844
3845 if (*(args[1]) == 0) {
3846 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
3849 }
3850
3851 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3852 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3853 file, linenum, args[0]);
3854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003858 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3859 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3860 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
3863 }
3864
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003865 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003866
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003867 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003868 rule->cond = cond;
3869 rule->srv.name = strdup(args[1]);
3870 LIST_INIT(&rule->list);
3871 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3872 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3873 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003874 else if ((!strcmp(args[0], "force-persist")) ||
3875 (!strcmp(args[0], "ignore-persist"))) {
3876 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003877
3878 if (curproxy == &defproxy) {
3879 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883
3884 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3885 err_code |= ERR_WARN;
3886
Willy Tarreauef6494c2010-01-28 17:12:36 +01003887 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003888 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3889 file, linenum, args[0]);
3890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
3892 }
3893
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003894 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3895 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3896 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
3899 }
3900
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003901 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3902 * where force-persist is applied.
3903 */
3904 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003905
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003906 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003907 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003908 if (!strcmp(args[0], "force-persist")) {
3909 rule->type = PERSIST_TYPE_FORCE;
3910 } else {
3911 rule->type = PERSIST_TYPE_IGNORE;
3912 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003913 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003914 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003915 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003916 else if (!strcmp(args[0], "stick-table")) {
3917 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003918 struct proxy *other;
3919
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003920 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003921 if (other) {
3922 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3923 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003927
Emeric Brun32da3c42010-09-23 18:39:19 +02003928 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003929 curproxy->table.type = (unsigned int)-1;
3930 while (*args[myidx]) {
3931 const char *err;
3932
3933 if (strcmp(args[myidx], "size") == 0) {
3934 myidx++;
3935 if (!*(args[myidx])) {
3936 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3937 file, linenum, args[myidx-1]);
3938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
3940 }
3941 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3942 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3943 file, linenum, *err, args[myidx-1]);
3944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
3946 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003947 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003948 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003949 else if (strcmp(args[myidx], "peers") == 0) {
3950 myidx++;
Godbach50523162013-12-11 19:48:57 +08003951 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003952 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3953 file, linenum, args[myidx-1]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
Godbach50523162013-12-11 19:48:57 +08003956 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003957 curproxy->table.peers.name = strdup(args[myidx++]);
3958 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003959 else if (strcmp(args[myidx], "expire") == 0) {
3960 myidx++;
3961 if (!*(args[myidx])) {
3962 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3963 file, linenum, args[myidx-1]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3968 if (err) {
3969 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3970 file, linenum, *err, args[myidx-1]);
3971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
3973 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003974 if (val > INT_MAX) {
3975 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3976 file, linenum, val);
3977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
3979 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003980 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003981 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003982 }
3983 else if (strcmp(args[myidx], "nopurge") == 0) {
3984 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003985 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003986 }
3987 else if (strcmp(args[myidx], "type") == 0) {
3988 myidx++;
3989 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3990 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3991 file, linenum, args[myidx]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003995 /* myidx already points to next arg */
3996 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003997 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003998 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003999 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004000
4001 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004002 nw = args[myidx];
4003 while (*nw) {
4004 /* the "store" keyword supports a comma-separated list */
4005 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004006 sa = NULL; /* store arg */
4007 while (*nw && *nw != ',') {
4008 if (*nw == '(') {
4009 *nw = 0;
4010 sa = ++nw;
4011 while (*nw != ')') {
4012 if (!*nw) {
4013 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4014 file, linenum, args[0], cw);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 nw++;
4019 }
4020 *nw = '\0';
4021 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004022 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004023 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004024 if (*nw)
4025 *nw++ = '\0';
4026 type = stktable_get_data_type(cw);
4027 if (type < 0) {
4028 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4029 file, linenum, args[0], cw);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
Willy Tarreauac782882010-06-20 10:41:54 +02004033
4034 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4035 switch (err) {
4036 case PE_NONE: break;
4037 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004038 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4039 file, linenum, args[0], cw);
4040 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004041 break;
4042
4043 case PE_ARG_MISSING:
4044 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4045 file, linenum, args[0], cw);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048
4049 case PE_ARG_NOT_USED:
4050 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4051 file, linenum, args[0], cw);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054
4055 default:
4056 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4057 file, linenum, args[0], cw);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004060 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004061 }
4062 myidx++;
4063 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004064 else {
4065 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4066 file, linenum, args[myidx]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004069 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004070 }
4071
4072 if (!curproxy->table.size) {
4073 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4074 file, linenum);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
4078
4079 if (curproxy->table.type == (unsigned int)-1) {
4080 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4081 file, linenum);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085 }
4086 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004087 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004088 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004089 int myidx = 0;
4090 const char *name = NULL;
4091 int flags;
4092
4093 if (curproxy == &defproxy) {
4094 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
4098
4099 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4100 err_code |= ERR_WARN;
4101 goto out;
4102 }
4103
4104 myidx++;
4105 if ((strcmp(args[myidx], "store") == 0) ||
4106 (strcmp(args[myidx], "store-request") == 0)) {
4107 myidx++;
4108 flags = STK_IS_STORE;
4109 }
4110 else if (strcmp(args[myidx], "store-response") == 0) {
4111 myidx++;
4112 flags = STK_IS_STORE | STK_ON_RSP;
4113 }
4114 else if (strcmp(args[myidx], "match") == 0) {
4115 myidx++;
4116 flags = STK_IS_MATCH;
4117 }
4118 else if (strcmp(args[myidx], "on") == 0) {
4119 myidx++;
4120 flags = STK_IS_MATCH | STK_IS_STORE;
4121 }
4122 else {
4123 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127
4128 if (*(args[myidx]) == 0) {
4129 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004134 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004135 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004136 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004137 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
4140 }
4141
4142 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004143 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4144 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4145 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004146 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004147 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004148 goto out;
4149 }
4150 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004151 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4152 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4153 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004154 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004155 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 goto out;
4157 }
4158 }
4159
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004160 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004161 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004162
Emeric Brunb982a3d2010-01-04 15:45:53 +01004163 if (strcmp(args[myidx], "table") == 0) {
4164 myidx++;
4165 name = args[myidx++];
4166 }
4167
Willy Tarreauef6494c2010-01-28 17:12:36 +01004168 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004169 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4170 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4171 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004172 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004173 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004174 goto out;
4175 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004176 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004177 else if (*(args[myidx])) {
4178 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4179 file, linenum, args[0], args[myidx]);
4180 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004181 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004182 goto out;
4183 }
Emeric Brun97679e72010-09-23 17:56:44 +02004184 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004185 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004186 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004187 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004188
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004189 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004190 rule->cond = cond;
4191 rule->expr = expr;
4192 rule->flags = flags;
4193 rule->table.name = name ? strdup(name) : NULL;
4194 LIST_INIT(&rule->list);
4195 if (flags & STK_ON_RSP)
4196 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4197 else
4198 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 else if (!strcmp(args[0], "stats")) {
4201 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4202 curproxy->uri_auth = NULL; /* we must detach from the default config */
4203
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004204 if (!*args[1]) {
4205 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004206 } else if (!strcmp(args[1], "admin")) {
4207 struct stats_admin_rule *rule;
4208
4209 if (curproxy == &defproxy) {
4210 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
4214
4215 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4216 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4217 err_code |= ERR_ALERT | ERR_ABORT;
4218 goto out;
4219 }
4220
4221 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4222 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4223 file, linenum, args[0], args[1]);
4224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
4226 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004227 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4228 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4229 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004234 err_code |= warnif_cond_conflicts(cond,
4235 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4236 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004237
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004238 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004239 rule->cond = cond;
4240 LIST_INIT(&rule->list);
4241 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 } else if (!strcmp(args[1], "uri")) {
4243 if (*(args[2]) == 0) {
4244 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4248 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_ALERT | ERR_ABORT;
4250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 }
4252 } else if (!strcmp(args[1], "realm")) {
4253 if (*(args[2]) == 0) {
4254 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4258 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_ABORT;
4260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004262 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004263 unsigned interval;
4264
4265 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4266 if (err) {
4267 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4268 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004271 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004273 err_code |= ERR_ALERT | ERR_ABORT;
4274 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004275 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004276 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004277 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004278
4279 if (curproxy == &defproxy) {
4280 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
4283 }
4284
4285 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4286 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4287 err_code |= ERR_ALERT | ERR_ABORT;
4288 goto out;
4289 }
4290
Willy Tarreauff011f22011-01-06 17:51:27 +01004291 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004292 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004293 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4294 file, linenum, args[0]);
4295 err_code |= ERR_WARN;
4296 }
4297
Willy Tarreauff011f22011-01-06 17:51:27 +01004298 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004299
Willy Tarreauff011f22011-01-06 17:51:27 +01004300 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004301 err_code |= ERR_ALERT | ERR_ABORT;
4302 goto out;
4303 }
4304
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004305 err_code |= warnif_cond_conflicts(rule->cond,
4306 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4307 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004308 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004309
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 } else if (!strcmp(args[1], "auth")) {
4311 if (*(args[2]) == 0) {
4312 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004317 err_code |= ERR_ALERT | ERR_ABORT;
4318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 }
4320 } else if (!strcmp(args[1], "scope")) {
4321 if (*(args[2]) == 0) {
4322 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004325 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4326 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_ABORT;
4328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 }
4330 } else if (!strcmp(args[1], "enable")) {
4331 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4332 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_ABORT;
4334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004336 } else if (!strcmp(args[1], "hide-version")) {
4337 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4338 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004339 err_code |= ERR_ALERT | ERR_ABORT;
4340 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004341 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004342 } else if (!strcmp(args[1], "show-legends")) {
4343 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4344 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4345 err_code |= ERR_ALERT | ERR_ABORT;
4346 goto out;
4347 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004348 } else if (!strcmp(args[1], "show-node")) {
4349
4350 if (*args[2]) {
4351 int i;
4352 char c;
4353
4354 for (i=0; args[2][i]; i++) {
4355 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004356 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4357 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004358 break;
4359 }
4360
4361 if (!i || args[2][i]) {
4362 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4363 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4364 file, linenum, args[0], args[1]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368 }
4369
4370 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4371 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4372 err_code |= ERR_ALERT | ERR_ABORT;
4373 goto out;
4374 }
4375 } else if (!strcmp(args[1], "show-desc")) {
4376 char *desc = NULL;
4377
4378 if (*args[2]) {
4379 int i, len=0;
4380 char *d;
4381
Willy Tarreau348acfe2014-04-14 15:00:39 +02004382 for (i = 2; *args[i]; i++)
4383 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004384
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004385 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004386
Willy Tarreau348acfe2014-04-14 15:00:39 +02004387 d += snprintf(d, desc + len - d, "%s", args[2]);
4388 for (i = 3; *args[i]; i++)
4389 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004390 }
4391
4392 if (!*args[2] && !global.desc)
4393 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4394 file, linenum, args[1]);
4395 else {
4396 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4397 free(desc);
4398 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4399 err_code |= ERR_ALERT | ERR_ABORT;
4400 goto out;
4401 }
4402 free(desc);
4403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004405stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004406 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 +01004407 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004410 }
4411 }
4412 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004413 int optnum;
4414
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004415 if (*(args[1]) == '\0') {
4416 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004421
4422 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4423 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004424 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4425 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4426 file, linenum, cfg_opts[optnum].name);
4427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
4429 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004430 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4431 goto out;
4432
Willy Tarreau93893792009-07-23 13:19:11 +02004433 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4434 err_code |= ERR_WARN;
4435 goto out;
4436 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004437
Willy Tarreau3842f002009-06-14 11:39:52 +02004438 curproxy->no_options &= ~cfg_opts[optnum].val;
4439 curproxy->options &= ~cfg_opts[optnum].val;
4440
4441 switch (kwm) {
4442 case KWM_STD:
4443 curproxy->options |= cfg_opts[optnum].val;
4444 break;
4445 case KWM_NO:
4446 curproxy->no_options |= cfg_opts[optnum].val;
4447 break;
4448 case KWM_DEF: /* already cleared */
4449 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004450 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004451
Willy Tarreau93893792009-07-23 13:19:11 +02004452 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004453 }
4454 }
4455
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004456 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4457 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004458 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4459 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4460 file, linenum, cfg_opts2[optnum].name);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004464 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4465 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004466 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4467 err_code |= ERR_WARN;
4468 goto out;
4469 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004470
Willy Tarreau3842f002009-06-14 11:39:52 +02004471 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4472 curproxy->options2 &= ~cfg_opts2[optnum].val;
4473
4474 switch (kwm) {
4475 case KWM_STD:
4476 curproxy->options2 |= cfg_opts2[optnum].val;
4477 break;
4478 case KWM_NO:
4479 curproxy->no_options2 |= cfg_opts2[optnum].val;
4480 break;
4481 case KWM_DEF: /* already cleared */
4482 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004483 }
Willy Tarreau93893792009-07-23 13:19:11 +02004484 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004485 }
4486 }
4487
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004488 /* HTTP options override each other. They can be cancelled using
4489 * "no option xxx" which only switches to default mode if the mode
4490 * was this one (useful for cancelling options set in defaults
4491 * sections).
4492 */
4493 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004494 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4495 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004496 if (kwm == KWM_STD) {
4497 curproxy->options &= ~PR_O_HTTP_MODE;
4498 curproxy->options |= PR_O_HTTP_PCL;
4499 goto out;
4500 }
4501 else if (kwm == KWM_NO) {
4502 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4503 curproxy->options &= ~PR_O_HTTP_MODE;
4504 goto out;
4505 }
4506 }
4507 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004508 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4509 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004510 if (kwm == KWM_STD) {
4511 curproxy->options &= ~PR_O_HTTP_MODE;
4512 curproxy->options |= PR_O_HTTP_FCL;
4513 goto out;
4514 }
4515 else if (kwm == KWM_NO) {
4516 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4517 curproxy->options &= ~PR_O_HTTP_MODE;
4518 goto out;
4519 }
4520 }
4521 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004522 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4523 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004524 if (kwm == KWM_STD) {
4525 curproxy->options &= ~PR_O_HTTP_MODE;
4526 curproxy->options |= PR_O_HTTP_SCL;
4527 goto out;
4528 }
4529 else if (kwm == KWM_NO) {
4530 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4531 curproxy->options &= ~PR_O_HTTP_MODE;
4532 goto out;
4533 }
4534 }
4535 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004536 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4537 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004538 if (kwm == KWM_STD) {
4539 curproxy->options &= ~PR_O_HTTP_MODE;
4540 curproxy->options |= PR_O_HTTP_KAL;
4541 goto out;
4542 }
4543 else if (kwm == KWM_NO) {
4544 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4545 curproxy->options &= ~PR_O_HTTP_MODE;
4546 goto out;
4547 }
4548 }
4549 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004550 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4551 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004552 if (kwm == KWM_STD) {
4553 curproxy->options &= ~PR_O_HTTP_MODE;
4554 curproxy->options |= PR_O_HTTP_TUN;
4555 goto out;
4556 }
4557 else if (kwm == KWM_NO) {
4558 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4559 curproxy->options &= ~PR_O_HTTP_MODE;
4560 goto out;
4561 }
4562 }
4563
Joseph Lynch726ab712015-05-11 23:25:34 -07004564 /* Redispatch can take an integer argument that control when the
4565 * resispatch occurs. All values are relative to the retries option.
4566 * This can be cancelled using "no option xxx".
4567 */
4568 if (strcmp(args[1], "redispatch") == 0) {
4569 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4570 err_code |= ERR_WARN;
4571 goto out;
4572 }
4573
4574 curproxy->no_options &= ~PR_O_REDISP;
4575 curproxy->options &= ~PR_O_REDISP;
4576
4577 switch (kwm) {
4578 case KWM_STD:
4579 curproxy->options |= PR_O_REDISP;
4580 curproxy->redispatch_after = -1;
4581 if(*args[2]) {
4582 curproxy->redispatch_after = atol(args[2]);
4583 }
4584 break;
4585 case KWM_NO:
4586 curproxy->no_options |= PR_O_REDISP;
4587 curproxy->redispatch_after = 0;
4588 break;
4589 case KWM_DEF: /* already cleared */
4590 break;
4591 }
4592 goto out;
4593 }
4594
Willy Tarreau3842f002009-06-14 11:39:52 +02004595 if (kwm != KWM_STD) {
4596 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004597 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004600 }
4601
Emeric Brun3a058f32009-06-30 18:26:00 +02004602 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004603 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004605 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004606 if (*(args[2]) != '\0') {
4607 if (!strcmp(args[2], "clf")) {
4608 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004609 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004610 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004611 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004614 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004615 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4616 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004617 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004618 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4619 char *oldlogformat = "log-format";
4620 char *clflogformat = "";
4621
4622 if (curproxy->conf.logformat_string == default_http_log_format)
4623 oldlogformat = "option httplog";
4624 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4625 oldlogformat = "option tcplog";
4626 else if (curproxy->conf.logformat_string == clf_http_log_format)
4627 oldlogformat = "option httplog clf";
4628 if (logformat == clf_http_log_format)
4629 clflogformat = " clf";
4630 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4631 file, linenum, clflogformat, oldlogformat);
4632 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004633 if (curproxy->conf.logformat_string != default_http_log_format &&
4634 curproxy->conf.logformat_string != default_tcp_log_format &&
4635 curproxy->conf.logformat_string != clf_http_log_format)
4636 free(curproxy->conf.logformat_string);
4637 curproxy->conf.logformat_string = logformat;
4638
4639 free(curproxy->conf.lfs_file);
4640 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4641 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004642 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004643 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004644 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4645 char *oldlogformat = "log-format";
4646
4647 if (curproxy->conf.logformat_string == default_http_log_format)
4648 oldlogformat = "option httplog";
4649 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4650 oldlogformat = "option tcplog";
4651 else if (curproxy->conf.logformat_string == clf_http_log_format)
4652 oldlogformat = "option httplog clf";
4653 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4654 file, linenum, oldlogformat);
4655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004657 if (curproxy->conf.logformat_string != default_http_log_format &&
4658 curproxy->conf.logformat_string != default_tcp_log_format &&
4659 curproxy->conf.logformat_string != clf_http_log_format)
4660 free(curproxy->conf.logformat_string);
4661 curproxy->conf.logformat_string = default_tcp_log_format;
4662
4663 free(curproxy->conf.lfs_file);
4664 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4665 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004666
4667 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4668 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004671 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004672 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004673 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004674
William Lallemanddf1425a2015-04-28 20:17:49 +02004675 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4676 goto out;
4677
Willy Tarreau13943ab2006-12-31 00:24:10 +01004678 if (curproxy->cap & PR_CAP_FE)
4679 curproxy->options |= PR_O_TCP_CLI_KA;
4680 if (curproxy->cap & PR_CAP_BE)
4681 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004682 }
4683 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004684 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004685 err_code |= ERR_WARN;
4686
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004688 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004689 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004690 curproxy->options2 &= ~PR_O2_CHK_ANY;
4691 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 if (!*args[2]) { /* no argument */
4693 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4694 curproxy->check_len = strlen(DEF_CHECK_REQ);
4695 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004696 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004697 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004699 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004701 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 if (*args[4])
4703 reqlen += strlen(args[4]);
4704 else
4705 reqlen += strlen("HTTP/1.0");
4706
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004707 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004709 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004711 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4712 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004713 }
4714 else if (!strcmp(args[1], "ssl-hello-chk")) {
4715 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004717 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004718
Willy Tarreaua534fea2008-08-03 12:19:50 +02004719 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004720 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004721 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004722 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004723
4724 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004726 }
Willy Tarreau23677902007-05-08 23:50:35 +02004727 else if (!strcmp(args[1], "smtpchk")) {
4728 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004729 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004730 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004731 curproxy->options2 &= ~PR_O2_CHK_ANY;
4732 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004733
4734 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4735 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4736 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4737 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4738 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4739 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004740 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004741 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4742 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4743 } else {
4744 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4745 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4746 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4747 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4748 }
4749 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004750 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4751 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004752 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004753 else if (!strcmp(args[1], "pgsql-check")) {
4754 /* use PostgreSQL request to check servers' health */
4755 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4756 err_code |= ERR_WARN;
4757
4758 free(curproxy->check_req);
4759 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004760 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004761 curproxy->options2 |= PR_O2_PGSQL_CHK;
4762
4763 if (*(args[2])) {
4764 int cur_arg = 2;
4765
4766 while (*(args[cur_arg])) {
4767 if (strcmp(args[cur_arg], "user") == 0) {
4768 char * packet;
4769 uint32_t packet_len;
4770 uint32_t pv;
4771
4772 /* suboption header - needs additional argument for it */
4773 if (*(args[cur_arg+1]) == 0) {
4774 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4775 file, linenum, args[0], args[1], args[cur_arg]);
4776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
4778 }
4779
4780 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4781 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4782 pv = htonl(0x30000); /* protocol version 3.0 */
4783
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004784 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004785
4786 memcpy(packet + 4, &pv, 4);
4787
4788 /* copy "user" */
4789 memcpy(packet + 8, "user", 4);
4790
4791 /* copy username */
4792 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4793
4794 free(curproxy->check_req);
4795 curproxy->check_req = packet;
4796 curproxy->check_len = packet_len;
4797
4798 packet_len = htonl(packet_len);
4799 memcpy(packet, &packet_len, 4);
4800 cur_arg += 2;
4801 } else {
4802 /* unknown suboption - catchall */
4803 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4804 file, linenum, args[0], args[1]);
4805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
4807 }
4808 } /* end while loop */
4809 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004810 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4811 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004812 }
4813
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004814 else if (!strcmp(args[1], "redis-check")) {
4815 /* use REDIS PING request to check servers' health */
4816 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4817 err_code |= ERR_WARN;
4818
4819 free(curproxy->check_req);
4820 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004821 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004822 curproxy->options2 |= PR_O2_REDIS_CHK;
4823
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004824 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004825 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4826 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004827
4828 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4829 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004830 }
4831
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004832 else if (!strcmp(args[1], "mysql-check")) {
4833 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4835 err_code |= ERR_WARN;
4836
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004837 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004838 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004839 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004840 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004841
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004842 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004843 * const char mysql40_client_auth_pkt[] = {
4844 * "\x0e\x00\x00" // packet length
4845 * "\x01" // packet number
4846 * "\x00\x00" // client capabilities
4847 * "\x00\x00\x01" // max packet
4848 * "haproxy\x00" // username (null terminated string)
4849 * "\x00" // filler (always 0x00)
4850 * "\x01\x00\x00" // packet length
4851 * "\x00" // packet number
4852 * "\x01" // COM_QUIT command
4853 * };
4854 */
4855
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004856 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4857 * const char mysql41_client_auth_pkt[] = {
4858 * "\x0e\x00\x00\" // packet length
4859 * "\x01" // packet number
4860 * "\x00\x00\x00\x00" // client capabilities
4861 * "\x00\x00\x00\x01" // max packet
4862 * "\x21" // character set (UTF-8)
4863 * char[23] // All zeroes
4864 * "haproxy\x00" // username (null terminated string)
4865 * "\x00" // filler (always 0x00)
4866 * "\x01\x00\x00" // packet length
4867 * "\x00" // packet number
4868 * "\x01" // COM_QUIT command
4869 * };
4870 */
4871
4872
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004873 if (*(args[2])) {
4874 int cur_arg = 2;
4875
4876 while (*(args[cur_arg])) {
4877 if (strcmp(args[cur_arg], "user") == 0) {
4878 char *mysqluser;
4879 int packetlen, reqlen, userlen;
4880
4881 /* suboption header - needs additional argument for it */
4882 if (*(args[cur_arg+1]) == 0) {
4883 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4884 file, linenum, args[0], args[1], args[cur_arg]);
4885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
4888 mysqluser = args[cur_arg + 1];
4889 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004890
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004891 if (*(args[cur_arg+2])) {
4892 if (!strcmp(args[cur_arg+2], "post-41")) {
4893 packetlen = userlen + 7 + 27;
4894 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004895
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004896 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004897 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004898 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004899
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004900 snprintf(curproxy->check_req, 4, "%c%c%c",
4901 ((unsigned char) packetlen & 0xff),
4902 ((unsigned char) (packetlen >> 8) & 0xff),
4903 ((unsigned char) (packetlen >> 16) & 0xff));
4904
4905 curproxy->check_req[3] = 1;
4906 curproxy->check_req[5] = 130;
4907 curproxy->check_req[11] = 1;
4908 curproxy->check_req[12] = 33;
4909 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4910 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4911 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4912 cur_arg += 3;
4913 } else {
4914 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
4917 }
4918 } else {
4919 packetlen = userlen + 7;
4920 reqlen = packetlen + 9;
4921
4922 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004923 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004924 curproxy->check_len = reqlen;
4925
4926 snprintf(curproxy->check_req, 4, "%c%c%c",
4927 ((unsigned char) packetlen & 0xff),
4928 ((unsigned char) (packetlen >> 8) & 0xff),
4929 ((unsigned char) (packetlen >> 16) & 0xff));
4930
4931 curproxy->check_req[3] = 1;
4932 curproxy->check_req[5] = 128;
4933 curproxy->check_req[8] = 1;
4934 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4935 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4936 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4937 cur_arg += 2;
4938 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004939 } else {
4940 /* unknown suboption - catchall */
4941 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4942 file, linenum, args[0], args[1]);
4943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
4946 } /* end while loop */
4947 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004948 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004949 else if (!strcmp(args[1], "ldap-check")) {
4950 /* use LDAP request to check servers' health */
4951 free(curproxy->check_req);
4952 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004953 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004954 curproxy->options2 |= PR_O2_LDAP_CHK;
4955
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004956 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004957 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4958 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004959 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4960 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004961 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004962 else if (!strcmp(args[1], "spop-check")) {
4963 if (curproxy == &defproxy) {
4964 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4965 file, linenum, args[0], args[1]);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
4969 if (curproxy->cap & PR_CAP_FE) {
4970 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4971 file, linenum, args[0], args[1]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975
4976 /* use SPOE request to check servers' health */
4977 free(curproxy->check_req);
4978 curproxy->check_req = NULL;
4979 curproxy->options2 &= ~PR_O2_CHK_ANY;
4980 curproxy->options2 |= PR_O2_SPOP_CHK;
4981
Christopher Faulet8ef75252017-02-20 22:56:03 +01004982 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01004983 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
4987 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4988 goto out;
4989 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004990 else if (!strcmp(args[1], "tcp-check")) {
4991 /* use raw TCPCHK send/expect to check servers' health */
4992 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4993 err_code |= ERR_WARN;
4994
4995 free(curproxy->check_req);
4996 curproxy->check_req = NULL;
4997 curproxy->options2 &= ~PR_O2_CHK_ANY;
4998 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004999 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5000 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005001 }
Simon Horman98637e52014-06-20 12:30:16 +09005002 else if (!strcmp(args[1], "external-check")) {
5003 /* excute an external command to check servers' health */
5004 free(curproxy->check_req);
5005 curproxy->check_req = NULL;
5006 curproxy->options2 &= ~PR_O2_CHK_ANY;
5007 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005008 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5009 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005010 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005011 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005012 int cur_arg;
5013
5014 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5015 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005016 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005017
Willy Tarreau87cf5142011-08-19 22:57:24 +02005018 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005019
5020 free(curproxy->fwdfor_hdr_name);
5021 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5022 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5023
5024 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5025 cur_arg = 2;
5026 while (*(args[cur_arg])) {
5027 if (!strcmp(args[cur_arg], "except")) {
5028 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005029 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005030 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5031 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005034 }
5035 /* flush useless bits */
5036 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005037 cur_arg += 2;
5038 } else if (!strcmp(args[cur_arg], "header")) {
5039 /* suboption header - needs additional argument for it */
5040 if (*(args[cur_arg+1]) == 0) {
5041 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5042 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005045 }
5046 free(curproxy->fwdfor_hdr_name);
5047 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5048 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5049 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005050 } else if (!strcmp(args[cur_arg], "if-none")) {
5051 curproxy->options &= ~PR_O_FF_ALWAYS;
5052 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005053 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005054 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005055 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005056 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005059 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005060 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005061 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005062 else if (!strcmp(args[1], "originalto")) {
5063 int cur_arg;
5064
5065 /* insert x-original-to field, but not for the IP address listed as an except.
5066 * set default options (ie: bitfield, header name, etc)
5067 */
5068
5069 curproxy->options |= PR_O_ORGTO;
5070
5071 free(curproxy->orgto_hdr_name);
5072 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5073 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5074
Willy Tarreau87cf5142011-08-19 22:57:24 +02005075 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005076 cur_arg = 2;
5077 while (*(args[cur_arg])) {
5078 if (!strcmp(args[cur_arg], "except")) {
5079 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005080 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 +02005081 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5082 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005085 }
5086 /* flush useless bits */
5087 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5088 cur_arg += 2;
5089 } else if (!strcmp(args[cur_arg], "header")) {
5090 /* suboption header - needs additional argument for it */
5091 if (*(args[cur_arg+1]) == 0) {
5092 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5093 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005096 }
5097 free(curproxy->orgto_hdr_name);
5098 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5099 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5100 cur_arg += 2;
5101 } else {
5102 /* unknown suboption - catchall */
5103 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5104 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005107 }
5108 } /* end while loop */
5109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 else {
5111 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
Willy Tarreau93893792009-07-23 13:19:11 +02005115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005117 else if (!strcmp(args[0], "default_backend")) {
5118 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005120
5121 if (*(args[1]) == 0) {
5122 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005125 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005126 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005127 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005128
5129 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5130 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005133 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005135
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005136 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5137 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 +01005138 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005139 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 /* enable reconnections to dispatch */
5141 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005142
5143 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005146 else if (!strcmp(args[0], "http-reuse")) {
5147 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5148 err_code |= ERR_WARN;
5149
5150 if (strcmp(args[1], "never") == 0) {
5151 /* enable a graceful server shutdown on an HTTP 404 response */
5152 curproxy->options &= ~PR_O_REUSE_MASK;
5153 curproxy->options |= PR_O_REUSE_NEVR;
5154 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5155 goto out;
5156 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005157 else if (strcmp(args[1], "safe") == 0) {
5158 /* enable a graceful server shutdown on an HTTP 404 response */
5159 curproxy->options &= ~PR_O_REUSE_MASK;
5160 curproxy->options |= PR_O_REUSE_SAFE;
5161 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5162 goto out;
5163 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005164 else if (strcmp(args[1], "aggressive") == 0) {
5165 curproxy->options &= ~PR_O_REUSE_MASK;
5166 curproxy->options |= PR_O_REUSE_AGGR;
5167 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5168 goto out;
5169 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005170 else if (strcmp(args[1], "always") == 0) {
5171 /* enable a graceful server shutdown on an HTTP 404 response */
5172 curproxy->options &= ~PR_O_REUSE_MASK;
5173 curproxy->options |= PR_O_REUSE_ALWS;
5174 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5175 goto out;
5176 }
5177 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005178 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
5182 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005183 else if (!strcmp(args[0], "http-check")) {
5184 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005185 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005186
5187 if (strcmp(args[1], "disable-on-404") == 0) {
5188 /* enable a graceful server shutdown on an HTTP 404 response */
5189 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005190 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5191 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005192 }
Willy Tarreauef781042010-01-27 11:53:01 +01005193 else if (strcmp(args[1], "send-state") == 0) {
5194 /* enable emission of the apparent state of a server in HTTP checks */
5195 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005196 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5197 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005198 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005199 else if (strcmp(args[1], "expect") == 0) {
5200 const char *ptr_arg;
5201 int cur_arg;
5202
5203 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5204 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
5207 }
5208
5209 cur_arg = 2;
5210 /* consider exclamation marks, sole or at the beginning of a word */
5211 while (*(ptr_arg = args[cur_arg])) {
5212 while (*ptr_arg == '!') {
5213 curproxy->options2 ^= PR_O2_EXP_INV;
5214 ptr_arg++;
5215 }
5216 if (*ptr_arg)
5217 break;
5218 cur_arg++;
5219 }
5220 /* now ptr_arg points to the beginning of a word past any possible
5221 * exclamation mark, and cur_arg is the argument which holds this word.
5222 */
5223 if (strcmp(ptr_arg, "status") == 0) {
5224 if (!*(args[cur_arg + 1])) {
5225 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5226 file, linenum, args[0], args[1], ptr_arg);
5227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229 }
5230 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005231 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005232 curproxy->expect_str = strdup(args[cur_arg + 1]);
5233 }
5234 else if (strcmp(ptr_arg, "string") == 0) {
5235 if (!*(args[cur_arg + 1])) {
5236 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5237 file, linenum, args[0], args[1], ptr_arg);
5238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
5240 }
5241 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005242 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005243 curproxy->expect_str = strdup(args[cur_arg + 1]);
5244 }
5245 else if (strcmp(ptr_arg, "rstatus") == 0) {
5246 if (!*(args[cur_arg + 1])) {
5247 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5248 file, linenum, args[0], args[1], ptr_arg);
5249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
5251 }
5252 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005253 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005254 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005255 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005256 free(curproxy->expect_regex);
5257 curproxy->expect_regex = NULL;
5258 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005259 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005260 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5261 error = NULL;
5262 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5263 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5264 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5265 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005266 err_code |= ERR_ALERT | ERR_FATAL;
5267 goto out;
5268 }
5269 }
5270 else if (strcmp(ptr_arg, "rstring") == 0) {
5271 if (!*(args[cur_arg + 1])) {
5272 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5273 file, linenum, args[0], args[1], ptr_arg);
5274 err_code |= ERR_ALERT | ERR_FATAL;
5275 goto out;
5276 }
5277 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005278 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005279 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005280 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005281 free(curproxy->expect_regex);
5282 curproxy->expect_regex = NULL;
5283 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005284 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005285 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5286 error = NULL;
5287 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5288 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5289 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5290 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
5293 }
5294 }
5295 else {
5296 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5297 file, linenum, args[0], args[1], ptr_arg);
5298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
5300 }
5301 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005302 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005303 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 +02005304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005306 }
5307 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005308 else if (!strcmp(args[0], "tcp-check")) {
5309 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5310 err_code |= ERR_WARN;
5311
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005312 if (strcmp(args[1], "comment") == 0) {
5313 int cur_arg;
5314 struct tcpcheck_rule *tcpcheck;
5315
5316 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005317 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005318 tcpcheck->action = TCPCHK_ACT_COMMENT;
5319
5320 if (!*args[cur_arg + 1]) {
5321 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5322 file, linenum, args[cur_arg]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326
5327 tcpcheck->comment = strdup(args[cur_arg + 1]);
5328
5329 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005330 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5331 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005332 }
5333 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005334 const char *ptr_arg;
5335 int cur_arg;
5336 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005337
5338 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005339 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5340 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5341 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5342 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5343 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005344
Willy Tarreau5581c272015-05-13 12:24:53 +02005345 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5346 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5347 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5348 file, linenum);
5349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005351 }
5352
5353 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005354 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005355 tcpcheck->action = TCPCHK_ACT_CONNECT;
5356
5357 /* parsing each parameters to fill up the rule */
5358 while (*(ptr_arg = args[cur_arg])) {
5359 /* tcp port */
5360 if (strcmp(args[cur_arg], "port") == 0) {
5361 if ( (atol(args[cur_arg + 1]) > 65535) ||
5362 (atol(args[cur_arg + 1]) < 1) ){
5363 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5364 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368 tcpcheck->port = atol(args[cur_arg + 1]);
5369 cur_arg += 2;
5370 }
5371 /* send proxy protocol */
5372 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5373 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5374 cur_arg++;
5375 }
5376#ifdef USE_OPENSSL
5377 else if (strcmp(args[cur_arg], "ssl") == 0) {
5378 curproxy->options |= PR_O_TCPCHK_SSL;
5379 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5380 cur_arg++;
5381 }
5382#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005383 /* comment for this tcpcheck line */
5384 else if (strcmp(args[cur_arg], "comment") == 0) {
5385 if (!*args[cur_arg + 1]) {
5386 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5387 file, linenum, args[cur_arg]);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
5391 tcpcheck->comment = strdup(args[cur_arg + 1]);
5392 cur_arg += 2;
5393 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005394 else {
5395#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005396 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 +01005397#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005398 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 +01005399#endif /* USE_OPENSSL */
5400 file, linenum, args[0], args[1], args[cur_arg]);
5401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
5403 }
5404
5405 }
5406
5407 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5408 }
5409 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005410 if (! *(args[2]) ) {
5411 /* SEND string expected */
5412 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5413 file, linenum, args[0], args[1], args[2]);
5414 err_code |= ERR_ALERT | ERR_FATAL;
5415 goto out;
5416 } else {
5417 struct tcpcheck_rule *tcpcheck;
5418
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005419 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005420
5421 tcpcheck->action = TCPCHK_ACT_SEND;
5422 tcpcheck->string_len = strlen(args[2]);
5423 tcpcheck->string = strdup(args[2]);
5424 tcpcheck->expect_regex = NULL;
5425
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005426 /* comment for this tcpcheck line */
5427 if (strcmp(args[3], "comment") == 0) {
5428 if (!*args[4]) {
5429 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5430 file, linenum, args[3]);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
5434 tcpcheck->comment = strdup(args[4]);
5435 }
5436
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005437 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5438 }
5439 }
5440 else if (strcmp(args[1], "send-binary") == 0) {
5441 if (! *(args[2]) ) {
5442 /* SEND binary string expected */
5443 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5444 file, linenum, args[0], args[1], args[2]);
5445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 } else {
5448 struct tcpcheck_rule *tcpcheck;
5449 char *err = NULL;
5450
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005451 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005452
5453 tcpcheck->action = TCPCHK_ACT_SEND;
5454 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5455 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5456 file, linenum, args[0], args[1], args[2], err);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
5460 tcpcheck->expect_regex = NULL;
5461
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005462 /* comment for this tcpcheck line */
5463 if (strcmp(args[3], "comment") == 0) {
5464 if (!*args[4]) {
5465 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5466 file, linenum, args[3]);
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
5470 tcpcheck->comment = strdup(args[4]);
5471 }
5472
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005473 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5474 }
5475 }
5476 else if (strcmp(args[1], "expect") == 0) {
5477 const char *ptr_arg;
5478 int cur_arg;
5479 int inverse = 0;
5480
5481 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5482 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
5486
5487 cur_arg = 2;
5488 /* consider exclamation marks, sole or at the beginning of a word */
5489 while (*(ptr_arg = args[cur_arg])) {
5490 while (*ptr_arg == '!') {
5491 inverse = !inverse;
5492 ptr_arg++;
5493 }
5494 if (*ptr_arg)
5495 break;
5496 cur_arg++;
5497 }
5498 /* now ptr_arg points to the beginning of a word past any possible
5499 * exclamation mark, and cur_arg is the argument which holds this word.
5500 */
5501 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005502 struct tcpcheck_rule *tcpcheck;
5503 char *err = NULL;
5504
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005505 if (!*(args[cur_arg + 1])) {
5506 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5507 file, linenum, args[0], args[1], ptr_arg);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
5510 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005511
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005512 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005513
5514 tcpcheck->action = TCPCHK_ACT_EXPECT;
5515 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5516 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5517 file, linenum, args[0], args[1], args[2], err);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521 tcpcheck->expect_regex = NULL;
5522 tcpcheck->inverse = inverse;
5523
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005524 /* tcpcheck comment */
5525 cur_arg += 2;
5526 if (strcmp(args[cur_arg], "comment") == 0) {
5527 if (!*args[cur_arg + 1]) {
5528 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5529 file, linenum, args[cur_arg + 1]);
5530 err_code |= ERR_ALERT | ERR_FATAL;
5531 goto out;
5532 }
5533 tcpcheck->comment = strdup(args[cur_arg + 1]);
5534 }
5535
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005536 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5537 }
5538 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005539 struct tcpcheck_rule *tcpcheck;
5540
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005541 if (!*(args[cur_arg + 1])) {
5542 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5543 file, linenum, args[0], args[1], ptr_arg);
5544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
5546 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005547
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005548 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005549
5550 tcpcheck->action = TCPCHK_ACT_EXPECT;
5551 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5552 tcpcheck->string = strdup(args[cur_arg + 1]);
5553 tcpcheck->expect_regex = NULL;
5554 tcpcheck->inverse = inverse;
5555
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005556 /* tcpcheck comment */
5557 cur_arg += 2;
5558 if (strcmp(args[cur_arg], "comment") == 0) {
5559 if (!*args[cur_arg + 1]) {
5560 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5561 file, linenum, args[cur_arg + 1]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565 tcpcheck->comment = strdup(args[cur_arg + 1]);
5566 }
5567
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005568 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5569 }
5570 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005571 struct tcpcheck_rule *tcpcheck;
5572
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005573 if (!*(args[cur_arg + 1])) {
5574 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5575 file, linenum, args[0], args[1], ptr_arg);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005579
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005580 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005581
5582 tcpcheck->action = TCPCHK_ACT_EXPECT;
5583 tcpcheck->string_len = 0;
5584 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005585 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5586 error = NULL;
5587 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5588 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5589 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5590 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
5593 }
5594 tcpcheck->inverse = inverse;
5595
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005596 /* tcpcheck comment */
5597 cur_arg += 2;
5598 if (strcmp(args[cur_arg], "comment") == 0) {
5599 if (!*args[cur_arg + 1]) {
5600 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5601 file, linenum, args[cur_arg + 1]);
5602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604 }
5605 tcpcheck->comment = strdup(args[cur_arg + 1]);
5606 }
5607
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005608 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5609 }
5610 else {
5611 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5612 file, linenum, args[0], args[1], ptr_arg);
5613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
5615 }
5616 }
5617 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005618 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
5622 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005623 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005624 if (curproxy == &defproxy) {
5625 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005628 }
5629
Willy Tarreaub80c2302007-11-30 20:51:32 +01005630 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005631 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005632
5633 if (strcmp(args[1], "fail") == 0) {
5634 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005635 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005636 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5637 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005640 }
5641
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005642 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5643 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5644 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005647 }
5648 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5649 }
5650 else {
5651 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005652 err_code |= ERR_ALERT | ERR_FATAL;
5653 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005654 }
5655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656#ifdef TPROXY
5657 else if (!strcmp(args[0], "transparent")) {
5658 /* enable transparent proxy connections */
5659 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005660 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 }
5663#endif
5664 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005665 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005666 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005667
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 if (*(args[1]) == 0) {
5669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 }
5673 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005674 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005677 else if (!strcmp(args[0], "backlog")) { /* backlog */
5678 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005679 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005680
5681 if (*(args[1]) == 0) {
5682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005685 }
5686 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005687 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5688 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005689 }
Willy Tarreau86034312006-12-29 00:10:33 +01005690 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005692 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005693
Willy Tarreau86034312006-12-29 00:10:33 +01005694 if (*(args[1]) == 0) {
5695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005696 err_code |= ERR_ALERT | ERR_FATAL;
5697 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005698 }
5699 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005700 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5701 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005702 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5704 if (*(args[1]) == 0) {
5705 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005709 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5710 if (err) {
5711 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5712 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005715 }
5716 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 }
5720 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005721 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005722 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005723 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005724
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725 if (curproxy == &defproxy) {
5726 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005730 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005731 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005732
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005733 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005734 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005735 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005736 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005737 goto out;
5738 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005739
5740 proto = protocol_by_family(sk->ss_family);
5741 if (!proto || !proto->connect) {
5742 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5743 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
5746 }
5747
5748 if (port1 != port2) {
5749 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5750 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005754
5755 if (!port1) {
5756 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5757 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
5760 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005761
William Lallemanddf1425a2015-04-28 20:17:49 +02005762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5763 goto out;
5764
Willy Tarreaud5191e72010-02-09 20:50:45 +01005765 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005766 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 }
5768 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005770 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005771
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005772 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5773 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005774 err_code |= ERR_ALERT | ERR_FATAL;
5775 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005776 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005778 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005779 /**
5780 * The syntax for hash-type config element is
5781 * hash-type {map-based|consistent} [[<algo>] avalanche]
5782 *
5783 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5784 */
5785 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005786
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005787 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5788 err_code |= ERR_WARN;
5789
5790 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005791 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5792 }
5793 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005794 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5795 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005796 else if (strcmp(args[1], "avalanche") == 0) {
5797 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]);
5798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005800 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005801 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005802 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005803 err_code |= ERR_ALERT | ERR_FATAL;
5804 goto out;
5805 }
Bhaskar98634f02013-10-29 23:30:51 -04005806
5807 /* set the hash function to use */
5808 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005809 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005810 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005811
5812 /* if consistent with no argument, then avalanche modifier is also applied */
5813 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5814 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005815 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005816 /* set the hash function */
5817 if (!strcmp(args[2], "sdbm")) {
5818 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5819 }
5820 else if (!strcmp(args[2], "djb2")) {
5821 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005822 }
5823 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005824 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005825 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005826 else if (!strcmp(args[2], "crc32")) {
5827 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5828 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005829 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005830 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 -05005831 err_code |= ERR_ALERT | ERR_FATAL;
5832 goto out;
5833 }
5834
5835 /* set the hash modifier */
5836 if (!strcmp(args[3], "avalanche")) {
5837 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5838 }
5839 else if (*args[3]) {
5840 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5841 err_code |= ERR_ALERT | ERR_FATAL;
5842 goto out;
5843 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005844 }
William Lallemanda73203e2012-03-12 12:48:57 +01005845 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005846 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5847 if (*(args[1]) == 0) {
5848 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5849 err_code |= ERR_ALERT | ERR_FATAL;
5850 goto out;
5851 }
5852 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5853 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5854 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5855 err_code |= ERR_ALERT | ERR_FATAL;
5856 goto out;
5857 }
5858 }
William Lallemanda73203e2012-03-12 12:48:57 +01005859 else if (strcmp(args[0], "unique-id-format") == 0) {
5860 if (!*(args[1])) {
5861 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
William Lallemand3203ff42012-11-11 17:30:56 +01005865 if (*(args[2])) {
5866 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
5869 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005870 free(curproxy->conf.uniqueid_format_string);
5871 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005872
Willy Tarreau62a61232013-04-12 18:13:46 +02005873 free(curproxy->conf.uif_file);
5874 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5875 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005876 }
William Lallemanda73203e2012-03-12 12:48:57 +01005877
5878 else if (strcmp(args[0], "unique-id-header") == 0) {
5879 if (!*(args[1])) {
5880 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
5883 }
5884 free(curproxy->header_unique_id);
5885 curproxy->header_unique_id = strdup(args[1]);
5886 }
5887
William Lallemand723b73a2012-02-08 16:37:49 +01005888 else if (strcmp(args[0], "log-format") == 0) {
5889 if (!*(args[1])) {
5890 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
5893 }
William Lallemand3203ff42012-11-11 17:30:56 +01005894 if (*(args[2])) {
5895 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
5898 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005899 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5900 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005901
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005902 if (curproxy->conf.logformat_string == default_http_log_format)
5903 oldlogformat = "option httplog";
5904 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5905 oldlogformat = "option tcplog";
5906 else if (curproxy->conf.logformat_string == clf_http_log_format)
5907 oldlogformat = "option httplog clf";
5908 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5909 file, linenum, oldlogformat);
5910 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005911 if (curproxy->conf.logformat_string != default_http_log_format &&
5912 curproxy->conf.logformat_string != default_tcp_log_format &&
5913 curproxy->conf.logformat_string != clf_http_log_format)
5914 free(curproxy->conf.logformat_string);
5915 curproxy->conf.logformat_string = strdup(args[1]);
5916
5917 free(curproxy->conf.lfs_file);
5918 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5919 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005920
5921 /* get a chance to improve log-format error reporting by
5922 * reporting the correct line-number when possible.
5923 */
5924 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5925 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5926 file, linenum, curproxy->id);
5927 err_code |= ERR_WARN;
5928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005929 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005930 else if (!strcmp(args[0], "log-format-sd")) {
5931 if (!*(args[1])) {
5932 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
5936 if (*(args[2])) {
5937 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
5940 }
5941
5942 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5943 free(curproxy->conf.logformat_sd_string);
5944 curproxy->conf.logformat_sd_string = strdup(args[1]);
5945
5946 free(curproxy->conf.lfsd_file);
5947 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5948 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5949
5950 /* get a chance to improve log-format-sd error reporting by
5951 * reporting the correct line-number when possible.
5952 */
5953 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5954 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5955 file, linenum, curproxy->id);
5956 err_code |= ERR_WARN;
5957 }
5958 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005959 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5960 if (*(args[1]) == 0) {
5961 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005965 chunk_destroy(&curproxy->log_tag);
5966 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005967 }
William Lallemand0f99e342011-10-12 17:50:54 +02005968 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5969 /* delete previous herited or defined syslog servers */
5970 struct logsrv *back;
5971
5972 if (*(args[1]) != 0) {
5973 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5974 err_code |= ERR_ALERT | ERR_FATAL;
5975 goto out;
5976 }
5977
William Lallemand723b73a2012-02-08 16:37:49 +01005978 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5979 LIST_DEL(&tmplogsrv->list);
5980 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005981 }
5982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005984 struct logsrv *logsrv;
5985
Willy Tarreaubaaee002006-06-26 02:48:02 +02005986 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005987 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005988 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005989 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005990 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005991 LIST_INIT(&node->list);
5992 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 }
5995 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005996 struct sockaddr_storage *sk;
5997 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005998 int arg = 0;
5999 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006000
Vincent Bernat02779b62016-04-03 13:48:43 +02006001 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006002
Willy Tarreau18324f52014-06-27 18:10:07 +02006003 /* just after the address, a length may be specified */
6004 if (strcmp(args[arg+2], "len") == 0) {
6005 len = atoi(args[arg+3]);
6006 if (len < 80 || len > 65535) {
6007 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6008 file, linenum, args[arg+3]);
6009 err_code |= ERR_ALERT | ERR_FATAL;
6010 goto out;
6011 }
6012 logsrv->maxlen = len;
6013
6014 /* skip these two args */
6015 arg += 2;
6016 }
6017 else
6018 logsrv->maxlen = MAX_SYSLOG_LEN;
6019
6020 if (logsrv->maxlen > global.max_syslog_len) {
6021 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006022 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6023 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6024 logline = my_realloc2(logline, global.max_syslog_len + 1);
6025 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006026 }
6027
Dragan Dosen1322d092015-09-22 16:05:32 +02006028 /* after the length, a format may be specified */
6029 if (strcmp(args[arg+2], "format") == 0) {
6030 logsrv->format = get_log_format(args[arg+3]);
6031 if (logsrv->format < 0) {
6032 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6033 err_code |= ERR_ALERT | ERR_FATAL;
6034 goto out;
6035 }
6036
6037 /* skip these two args */
6038 arg += 2;
6039 }
6040
William Lallemanddf1425a2015-04-28 20:17:49 +02006041 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6042 goto out;
6043
Willy Tarreau18324f52014-06-27 18:10:07 +02006044 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006045 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006046 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006047 err_code |= ERR_ALERT | ERR_FATAL;
6048 goto out;
6049
Willy Tarreaubaaee002006-06-26 02:48:02 +02006050 }
6051
William Lallemand0f99e342011-10-12 17:50:54 +02006052 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006053 if (*(args[arg+3])) {
6054 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006055 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006056 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006057 err_code |= ERR_ALERT | ERR_FATAL;
6058 goto out;
6059
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 }
6061 }
6062
William Lallemand0f99e342011-10-12 17:50:54 +02006063 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006064 if (*(args[arg+4])) {
6065 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006066 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006067 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006071 }
6072 }
6073
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006074 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006075 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006076 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006077 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006078 goto out;
6079 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006080
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006081 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006082
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006083 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006084 if (port1 != port2) {
6085 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6086 file, linenum, args[0], args[1]);
6087 err_code |= ERR_ALERT | ERR_FATAL;
6088 goto out;
6089 }
6090
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006091 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006092 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093 }
William Lallemand0f99e342011-10-12 17:50:54 +02006094
6095 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006096 }
6097 else {
6098 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6099 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006100 err_code |= ERR_ALERT | ERR_FATAL;
6101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102 }
6103 }
6104 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006105 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006106 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006107 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006108 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006109
Willy Tarreau977b8e42006-12-29 14:19:17 +01006110 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006111 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006112
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006114 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6115 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006116 err_code |= ERR_ALERT | ERR_FATAL;
6117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006119
6120 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006121 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6122 free(curproxy->conn_src.iface_name);
6123 curproxy->conn_src.iface_name = NULL;
6124 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006125
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006126 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006127 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006128 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006129 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006130 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006131 goto out;
6132 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006133
6134 proto = protocol_by_family(sk->ss_family);
6135 if (!proto || !proto->connect) {
6136 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006137 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
6140 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006141
6142 if (port1 != port2) {
6143 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6144 file, linenum, args[0], args[1]);
6145 err_code |= ERR_ALERT | ERR_FATAL;
6146 goto out;
6147 }
6148
Willy Tarreauef9a3602012-12-08 22:29:20 +01006149 curproxy->conn_src.source_addr = *sk;
6150 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006151
6152 cur_arg = 2;
6153 while (*(args[cur_arg])) {
6154 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006155#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006156 if (!*args[cur_arg + 1]) {
6157 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6158 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006159 err_code |= ERR_ALERT | ERR_FATAL;
6160 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006161 }
6162
6163 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006164 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6165 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006166 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006167 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6168 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006169 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6170 char *name, *end;
6171
6172 name = args[cur_arg+1] + 7;
6173 while (isspace(*name))
6174 name++;
6175
6176 end = name;
6177 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6178 end++;
6179
Willy Tarreauef9a3602012-12-08 22:29:20 +01006180 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6181 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6182 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6183 curproxy->conn_src.bind_hdr_len = end - name;
6184 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6185 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6186 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006187
6188 /* now look for an occurrence number */
6189 while (isspace(*end))
6190 end++;
6191 if (*end == ',') {
6192 end++;
6193 name = end;
6194 if (*end == '-')
6195 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006196 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006197 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006198 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006199 }
6200
Willy Tarreauef9a3602012-12-08 22:29:20 +01006201 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006202 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6203 " occurrences values smaller than %d.\n",
6204 file, linenum, MAX_HDR_HISTORY);
6205 err_code |= ERR_ALERT | ERR_FATAL;
6206 goto out;
6207 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006208 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006209 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006210
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006211 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006212 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006213 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006214 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006215 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006216 goto out;
6217 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006218
6219 proto = protocol_by_family(sk->ss_family);
6220 if (!proto || !proto->connect) {
6221 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6222 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006223 err_code |= ERR_ALERT | ERR_FATAL;
6224 goto out;
6225 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006226
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006227 if (port1 != port2) {
6228 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6229 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006230 err_code |= ERR_ALERT | ERR_FATAL;
6231 goto out;
6232 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006233 curproxy->conn_src.tproxy_addr = *sk;
6234 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006235 }
6236 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006237#else /* no TPROXY support */
6238 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006239 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006240 err_code |= ERR_ALERT | ERR_FATAL;
6241 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006242#endif
6243 cur_arg += 2;
6244 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006245 }
6246
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006247 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6248#ifdef SO_BINDTODEVICE
6249 if (!*args[cur_arg + 1]) {
6250 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6251 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006252 err_code |= ERR_ALERT | ERR_FATAL;
6253 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006254 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006255 free(curproxy->conn_src.iface_name);
6256 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6257 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006258 global.last_checks |= LSTCHK_NETADM;
6259#else
6260 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6261 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006262 err_code |= ERR_ALERT | ERR_FATAL;
6263 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006264#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006265 cur_arg += 2;
6266 continue;
6267 }
6268 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006269 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006270 err_code |= ERR_ALERT | ERR_FATAL;
6271 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006274 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6275 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6276 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006277 err_code |= ERR_ALERT | ERR_FATAL;
6278 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006281 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6283 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006284 err_code |= ERR_ALERT | ERR_FATAL;
6285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006287
6288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006289 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006290 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
6294 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006296 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006300 }
6301 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006302 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006303 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006304 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006305 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006307 }
6308 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006309 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006310 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006311 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006312 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 }
6315 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006316 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006317 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006318 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006319 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006322 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006323 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006324 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006325 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006326 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006327 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006330 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006331 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6332 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006333 err_code |= ERR_ALERT | ERR_FATAL;
6334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006336
6337 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006338 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006339 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006340 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 }
6343 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006345 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006346 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006347 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 }
6350 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006352 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006353 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006354 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356 }
6357 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006359 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006360 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 }
6364 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006366 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006371 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006373 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006376 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006379 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006380
Willy Tarreaubaaee002006-06-26 02:48:02 +02006381 if (curproxy == &defproxy) {
6382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006383 err_code |= ERR_ALERT | ERR_FATAL;
6384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006386 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006387 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388
Willy Tarreaubaaee002006-06-26 02:48:02 +02006389 if (*(args[1]) == 0) {
6390 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006391 err_code |= ERR_ALERT | ERR_FATAL;
6392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006394
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006395 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006396 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6397 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6398 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006399 err_code |= ERR_ALERT | ERR_FATAL;
6400 goto out;
6401 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006402 err_code |= warnif_cond_conflicts(cond,
6403 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6404 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006405 }
6406 else if (*args[2]) {
6407 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6408 file, linenum, args[0], args[2]);
6409 err_code |= ERR_ALERT | ERR_FATAL;
6410 goto out;
6411 }
6412
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006413 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006414 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006415 wl->s = strdup(args[1]);
6416 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006417 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 }
6419 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006420 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6422 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006423 err_code |= ERR_ALERT | ERR_FATAL;
6424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006426
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006428 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006429 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006430 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006432 }
6433 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006434 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006435 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006436 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006437 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439 }
6440 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006441 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006442 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006443 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006444 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 }
6447 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006448 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006451 err_code |= ERR_ALERT | ERR_FATAL;
6452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 }
6454
Willy Tarreauade5ec42010-01-28 19:33:49 +01006455 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006456 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006457 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006458 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 }
6461 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006463 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006464 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006465 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 }
6468 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006469 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006470 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006471 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006472 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 }
6475 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006476 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006477
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 if (curproxy == &defproxy) {
6479 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006480 err_code |= ERR_ALERT | ERR_FATAL;
6481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006483 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006484 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485
Willy Tarreaubaaee002006-06-26 02:48:02 +02006486 if (*(args[1]) == 0) {
6487 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006488 err_code |= ERR_ALERT | ERR_FATAL;
6489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490 }
6491
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006492 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006493 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6494 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6495 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006496 err_code |= ERR_ALERT | ERR_FATAL;
6497 goto out;
6498 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006499 err_code |= warnif_cond_conflicts(cond,
6500 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6501 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006502 }
6503 else if (*args[2]) {
6504 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6505 file, linenum, args[0], args[2]);
6506 err_code |= ERR_ALERT | ERR_FATAL;
6507 goto out;
6508 }
6509
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006510 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006511 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006512 wl->s = strdup(args[1]);
6513 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006514 }
6515 else if (!strcmp(args[0], "errorloc") ||
6516 !strcmp(args[0], "errorloc302") ||
6517 !strcmp(args[0], "errorloc303")) { /* error location */
6518 int errnum, errlen;
6519 char *err;
6520
Willy Tarreau977b8e42006-12-29 14:19:17 +01006521 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006522 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006523
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006525 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006526 err_code |= ERR_ALERT | ERR_FATAL;
6527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006528 }
6529
6530 errnum = atol(args[1]);
6531 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006532 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6533 err = malloc(errlen);
6534 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006535 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006536 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6537 err = malloc(errlen);
6538 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006539 }
6540
Willy Tarreau0f772532006-12-23 20:51:41 +01006541 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6542 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006543 chunk_destroy(&curproxy->errmsg[rc]);
6544 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006545 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006548
6549 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006550 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6551 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 free(err);
6553 }
6554 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006555 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6556 int errnum, errlen, fd;
6557 char *err;
6558 struct stat stat;
6559
6560 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006561 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006562
6563 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006564 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006565 err_code |= ERR_ALERT | ERR_FATAL;
6566 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006567 }
6568
6569 fd = open(args[2], O_RDONLY);
6570 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6571 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6572 file, linenum, args[2], args[1]);
6573 if (fd >= 0)
6574 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006575 err_code |= ERR_ALERT | ERR_FATAL;
6576 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006577 }
6578
Willy Tarreau27a674e2009-08-17 07:23:33 +02006579 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006580 errlen = stat.st_size;
6581 } else {
6582 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006583 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006584 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006585 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006586 }
6587
6588 err = malloc(errlen); /* malloc() must succeed during parsing */
6589 errnum = read(fd, err, errlen);
6590 if (errnum != errlen) {
6591 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6592 file, linenum, args[2], args[1]);
6593 close(fd);
6594 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006595 err_code |= ERR_ALERT | ERR_FATAL;
6596 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006597 }
6598 close(fd);
6599
6600 errnum = atol(args[1]);
6601 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6602 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006603 chunk_destroy(&curproxy->errmsg[rc]);
6604 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006605 break;
6606 }
6607 }
6608
6609 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006610 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6611 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006612 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006613 free(err);
6614 }
6615 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006617 struct cfg_kw_list *kwl;
6618 int index;
6619
6620 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6621 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6622 if (kwl->kw[index].section != CFG_LISTEN)
6623 continue;
6624 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6625 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006626 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006627 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006628 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006629 err_code |= ERR_ALERT | ERR_FATAL;
6630 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006631 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006632 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006633 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006634 err_code |= ERR_WARN;
6635 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006636 }
Willy Tarreau93893792009-07-23 13:19:11 +02006637 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006638 }
6639 }
6640 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006641
Willy Tarreau6daf3432008-01-22 16:44:08 +01006642 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006643 err_code |= ERR_ALERT | ERR_FATAL;
6644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006645 }
Willy Tarreau93893792009-07-23 13:19:11 +02006646 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006647 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006648 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006649}
6650
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006651int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006652cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6653{
6654#ifdef CONFIG_HAP_NS
6655 const char *err;
6656 const char *item = args[0];
6657
6658 if (!strcmp(item, "namespace_list")) {
6659 return 0;
6660 }
6661 else if (!strcmp(item, "namespace")) {
6662 size_t idx = 1;
6663 const char *current;
6664 while (*(current = args[idx++])) {
6665 err = invalid_char(current);
6666 if (err) {
6667 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6668 file, linenum, *err, item, current);
6669 return ERR_ALERT | ERR_FATAL;
6670 }
6671
6672 if (netns_store_lookup(current, strlen(current))) {
6673 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6674 file, linenum, current);
6675 return ERR_ALERT | ERR_FATAL;
6676 }
6677 if (!netns_store_insert(current)) {
6678 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6679 file, linenum, current);
6680 return ERR_ALERT | ERR_FATAL;
6681 }
6682 }
6683 }
6684
6685 return 0;
6686#else
6687 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6688 file, linenum);
6689 return ERR_ALERT | ERR_FATAL;
6690#endif
6691}
6692
6693int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006694cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6695{
6696
6697 int err_code = 0;
6698 const char *err;
6699
6700 if (!strcmp(args[0], "userlist")) { /* new userlist */
6701 struct userlist *newul;
6702
6703 if (!*args[1]) {
6704 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6705 file, linenum, args[0]);
6706 err_code |= ERR_ALERT | ERR_FATAL;
6707 goto out;
6708 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006709 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6710 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006711
6712 err = invalid_char(args[1]);
6713 if (err) {
6714 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6715 file, linenum, *err, args[0], args[1]);
6716 err_code |= ERR_ALERT | ERR_FATAL;
6717 goto out;
6718 }
6719
6720 for (newul = userlist; newul; newul = newul->next)
6721 if (!strcmp(newul->name, args[1])) {
6722 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6723 file, linenum, args[1]);
6724 err_code |= ERR_WARN;
6725 goto out;
6726 }
6727
Vincent Bernat02779b62016-04-03 13:48:43 +02006728 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006729 if (!newul) {
6730 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6731 err_code |= ERR_ALERT | ERR_ABORT;
6732 goto out;
6733 }
6734
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006735 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006736 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006737 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6738 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006739 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006740 goto out;
6741 }
6742
6743 newul->next = userlist;
6744 userlist = newul;
6745
6746 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006747 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006748 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006749 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006750
6751 if (!*args[1]) {
6752 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6753 file, linenum, args[0]);
6754 err_code |= ERR_ALERT | ERR_FATAL;
6755 goto out;
6756 }
6757
6758 err = invalid_char(args[1]);
6759 if (err) {
6760 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6761 file, linenum, *err, args[0], args[1]);
6762 err_code |= ERR_ALERT | ERR_FATAL;
6763 goto out;
6764 }
6765
William Lallemand4ac9f542015-05-28 18:03:51 +02006766 if (!userlist)
6767 goto out;
6768
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006769 for (ag = userlist->groups; ag; ag = ag->next)
6770 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006771 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6772 file, linenum, args[1], userlist->name);
6773 err_code |= ERR_ALERT;
6774 goto out;
6775 }
6776
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006777 ag = calloc(1, sizeof(*ag));
6778 if (!ag) {
6779 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6780 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006781 goto out;
6782 }
6783
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006784 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006785 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006786 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6787 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006788 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006789 goto out;
6790 }
6791
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 cur_arg = 2;
6793
6794 while (*args[cur_arg]) {
6795 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006796 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006797 cur_arg += 2;
6798 continue;
6799 } else {
6800 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6801 file, linenum, args[0]);
6802 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006803 free(ag->groupusers);
6804 free(ag->name);
6805 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006806 goto out;
6807 }
6808 }
6809
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006810 ag->next = userlist->groups;
6811 userlist->groups = ag;
6812
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813 } else if (!strcmp(args[0], "user")) { /* new user */
6814 struct auth_users *newuser;
6815 int cur_arg;
6816
6817 if (!*args[1]) {
6818 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6819 file, linenum, args[0]);
6820 err_code |= ERR_ALERT | ERR_FATAL;
6821 goto out;
6822 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006823 if (!userlist)
6824 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006825
6826 for (newuser = userlist->users; newuser; newuser = newuser->next)
6827 if (!strcmp(newuser->user, args[1])) {
6828 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6829 file, linenum, args[1], userlist->name);
6830 err_code |= ERR_ALERT;
6831 goto out;
6832 }
6833
Vincent Bernat02779b62016-04-03 13:48:43 +02006834 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006835 if (!newuser) {
6836 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6837 err_code |= ERR_ALERT | ERR_ABORT;
6838 goto out;
6839 }
6840
6841 newuser->user = strdup(args[1]);
6842
6843 newuser->next = userlist->users;
6844 userlist->users = newuser;
6845
6846 cur_arg = 2;
6847
6848 while (*args[cur_arg]) {
6849 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006850#ifdef CONFIG_HAP_CRYPT
6851 if (!crypt("", args[cur_arg + 1])) {
6852 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6853 file, linenum, newuser->user);
6854 err_code |= ERR_ALERT | ERR_FATAL;
6855 goto out;
6856 }
6857#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006858 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6859 file, linenum);
6860 err_code |= ERR_ALERT;
6861#endif
6862 newuser->pass = strdup(args[cur_arg + 1]);
6863 cur_arg += 2;
6864 continue;
6865 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6866 newuser->pass = strdup(args[cur_arg + 1]);
6867 newuser->flags |= AU_O_INSECURE;
6868 cur_arg += 2;
6869 continue;
6870 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006871 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006872 cur_arg += 2;
6873 continue;
6874 } else {
6875 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6876 file, linenum, args[0]);
6877 err_code |= ERR_ALERT | ERR_FATAL;
6878 goto out;
6879 }
6880 }
6881 } else {
6882 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6883 err_code |= ERR_ALERT | ERR_FATAL;
6884 }
6885
6886out:
6887 return err_code;
6888}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006889
Christopher Faulet79bdef32016-11-04 22:36:15 +01006890int
6891cfg_parse_scope(const char *file, int linenum, char *line)
6892{
6893 char *beg, *end, *scope = NULL;
6894 int err_code = 0;
6895 const char *err;
6896
6897 beg = line + 1;
6898 end = strchr(beg, ']');
6899
6900 /* Detect end of scope declaration */
6901 if (!end || end == beg) {
6902 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6903 file, linenum);
6904 err_code |= ERR_ALERT | ERR_FATAL;
6905 goto out;
6906 }
6907
6908 /* Get scope name and check its validity */
6909 scope = my_strndup(beg, end-beg);
6910 err = invalid_char(scope);
6911 if (err) {
6912 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6913 file, linenum, *err);
6914 err_code |= ERR_ALERT | ERR_ABORT;
6915 goto out;
6916 }
6917
6918 /* Be sure to have a scope declaration alone on its line */
6919 line = end+1;
6920 while (isspace((unsigned char)*line))
6921 line++;
6922 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6923 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6924 file, linenum, *line);
6925 err_code |= ERR_ALERT | ERR_ABORT;
6926 goto out;
6927 }
6928
6929 /* We have a valid scope declaration, save it */
6930 free(cfg_scope);
6931 cfg_scope = scope;
6932 scope = NULL;
6933
6934 out:
6935 free(scope);
6936 return err_code;
6937}
6938
Willy Tarreaubaaee002006-06-26 02:48:02 +02006939/*
6940 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006941 * Returns the error code, 0 if OK, or any combination of :
6942 * - ERR_ABORT: must abort ASAP
6943 * - ERR_FATAL: we can continue parsing but not start the service
6944 * - ERR_WARN: a warning has been emitted
6945 * - ERR_ALERT: an alert has been emitted
6946 * Only the two first ones can stop processing, the two others are just
6947 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006948 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006949int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950{
William Lallemand64e84512015-05-12 14:25:37 +02006951 char *thisline;
6952 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006953 FILE *f;
6954 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006955 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006956 struct cfg_section *cs = NULL;
6957 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006958 int readbytes = 0;
6959
6960 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006961 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006962 return -1;
6963 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006964
David Carlier97880bb2016-04-08 10:35:26 +01006965 if ((f=fopen(file,"r")) == NULL) {
6966 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006967 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006969
William Lallemandb2f07452015-05-12 14:27:13 +02006970next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006971 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006972 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006973 char *end;
6974 char *args[MAX_LINE_ARGS + 1];
6975 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006976 int dquote = 0; /* double quote */
6977 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006978
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979 linenum++;
6980
6981 end = line + strlen(line);
6982
William Lallemand64e84512015-05-12 14:25:37 +02006983 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006984 /* Check if we reached the limit and the last char is not \n.
6985 * Watch out for the last line without the terminating '\n'!
6986 */
William Lallemand64e84512015-05-12 14:25:37 +02006987 char *newline;
6988 int newlinesize = linesize * 2;
6989
6990 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6991 if (newline == NULL) {
6992 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6993 file, linenum);
6994 err_code |= ERR_ALERT | ERR_FATAL;
6995 continue;
6996 }
6997
6998 readbytes = linesize - 1;
6999 linesize = newlinesize;
7000 thisline = newline;
7001 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007002 }
7003
William Lallemand64e84512015-05-12 14:25:37 +02007004 readbytes = 0;
7005
Willy Tarreaubaaee002006-06-26 02:48:02 +02007006 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007007 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007009
Christopher Faulet79bdef32016-11-04 22:36:15 +01007010
7011 if (*line == '[') {/* This is the begining if a scope */
7012 err_code |= cfg_parse_scope(file, linenum, line);
7013 goto next_line;
7014 }
7015
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 arg = 0;
7017 args[arg] = line;
7018
7019 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007020 if (*line == '"' && !squote) { /* double quote outside single quotes */
7021 if (dquote)
7022 dquote = 0;
7023 else
7024 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007025 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007026 end--;
7027 }
7028 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7029 if (squote)
7030 squote = 0;
7031 else
7032 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007033 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007034 end--;
7035 }
7036 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7038 * C equivalent value. Other combinations left unchanged (eg: \1).
7039 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007040 int skip = 0;
7041 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7042 *line = line[1];
7043 skip = 1;
7044 }
7045 else if (line[1] == 'r') {
7046 *line = '\r';
7047 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007049 else if (line[1] == 'n') {
7050 *line = '\n';
7051 skip = 1;
7052 }
7053 else if (line[1] == 't') {
7054 *line = '\t';
7055 skip = 1;
7056 }
7057 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007058 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007059 unsigned char hex1, hex2;
7060 hex1 = toupper(line[2]) - '0';
7061 hex2 = toupper(line[3]) - '0';
7062 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7063 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7064 *line = (hex1<<4) + hex2;
7065 skip = 3;
7066 }
7067 else {
7068 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007069 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007070 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007071 } else if (line[1] == '"') {
7072 *line = '"';
7073 skip = 1;
7074 } else if (line[1] == '\'') {
7075 *line = '\'';
7076 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007077 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7078 *line = '$';
7079 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 }
7081 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007082 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007083 end -= skip;
7084 }
7085 line++;
7086 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007087 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088 /* end of string, end of loop */
7089 *line = 0;
7090 break;
7091 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007092 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007094 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007095 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 line++;
7097 args[++arg] = line;
7098 }
William Lallemandb2f07452015-05-12 14:27:13 +02007099 else if (dquote && *line == '$') {
7100 /* environment variables are evaluated inside double quotes */
7101 char *var_beg;
7102 char *var_end;
7103 char save_char;
7104 char *value;
7105 int val_len;
7106 int newlinesize;
7107 int braces = 0;
7108
7109 var_beg = line + 1;
7110 var_end = var_beg;
7111
7112 if (*var_beg == '{') {
7113 var_beg++;
7114 var_end++;
7115 braces = 1;
7116 }
7117
7118 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7119 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7120 err_code |= ERR_ALERT | ERR_FATAL;
7121 goto next_line; /* skip current line */
7122 }
7123
7124 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7125 var_end++;
7126
7127 save_char = *var_end;
7128 *var_end = '\0';
7129 value = getenv(var_beg);
7130 *var_end = save_char;
7131 val_len = value ? strlen(value) : 0;
7132
7133 if (braces) {
7134 if (*var_end == '}') {
7135 var_end++;
7136 braces = 0;
7137 } else {
7138 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7139 err_code |= ERR_ALERT | ERR_FATAL;
7140 goto next_line; /* skip current line */
7141 }
7142 }
7143
7144 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7145
7146 /* if not enough space in thisline */
7147 if (newlinesize > linesize) {
7148 char *newline;
7149
7150 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7151 if (newline == NULL) {
7152 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7153 err_code |= ERR_ALERT | ERR_FATAL;
7154 goto next_line; /* slip current line */
7155 }
7156 /* recompute pointers if realloc returns a new pointer */
7157 if (newline != thisline) {
7158 int i;
7159 int diff;
7160
7161 for (i = 0; i <= arg; i++) {
7162 diff = args[i] - thisline;
7163 args[i] = newline + diff;
7164 }
7165
7166 diff = var_end - thisline;
7167 var_end = newline + diff;
7168 diff = end - thisline;
7169 end = newline + diff;
7170 diff = line - thisline;
7171 line = newline + diff;
7172 thisline = newline;
7173 }
7174 linesize = newlinesize;
7175 }
7176
7177 /* insert value inside the line */
7178 memmove(line + val_len, var_end, end - var_end + 1);
7179 memcpy(line, value, val_len);
7180 end += val_len - (var_end - line);
7181 line += val_len;
7182 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007183 else {
7184 line++;
7185 }
7186 }
William Lallemandb2f07452015-05-12 14:27:13 +02007187
William Lallemandf9873ba2015-05-05 17:37:14 +02007188 if (dquote) {
7189 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7190 err_code |= ERR_ALERT | ERR_FATAL;
7191 }
7192
7193 if (squote) {
7194 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7195 err_code |= ERR_ALERT | ERR_FATAL;
7196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007197
7198 /* empty line */
7199 if (!**args)
7200 continue;
7201
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007202 if (*line) {
7203 /* we had to stop due to too many args.
7204 * Let's terminate the string, print the offending part then cut the
7205 * last arg.
7206 */
7207 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7208 line++;
7209 *line = '\0';
7210
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007211 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007212 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007213 err_code |= ERR_ALERT | ERR_FATAL;
7214 args[arg] = line;
7215 }
7216
Willy Tarreau540abe42007-05-02 20:50:16 +02007217 /* zero out remaining args and ensure that at least one entry
7218 * is zeroed out.
7219 */
7220 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007221 args[arg] = line;
7222 }
7223
Willy Tarreau3842f002009-06-14 11:39:52 +02007224 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007225 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007226 char *tmp;
7227
Willy Tarreau3842f002009-06-14 11:39:52 +02007228 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007229 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007230 for (arg=0; *args[arg+1]; arg++)
7231 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007232 *tmp = '\0'; // fix the next arg to \0
7233 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007234 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007235 else if (!strcmp(args[0], "default")) {
7236 kwm = KWM_DEF;
7237 for (arg=0; *args[arg+1]; arg++)
7238 args[arg] = args[arg+1]; // shift args after inversion
7239 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007240
William Lallemand0f99e342011-10-12 17:50:54 +02007241 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7242 strcmp(args[0], "log") != 0) {
7243 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007244 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007245 }
7246
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007247 /* detect section start */
7248 list_for_each_entry(ics, &sections, list) {
7249 if (strcmp(args[0], ics->section_name) == 0) {
7250 cursection = ics->section_name;
7251 cs = ics;
7252 break;
7253 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007254 }
7255
Willy Tarreaubaaee002006-06-26 02:48:02 +02007256 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007257 if (cs)
7258 err_code |= cs->section_parser(file, linenum, args, kwm);
7259 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007260 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007261 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007262 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007263
7264 if (err_code & ERR_ABORT)
7265 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007266 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007267 free(cfg_scope);
7268 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007269 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007270 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007271 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007272 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007273}
7274
Willy Tarreau64ab6072014-09-16 12:17:36 +02007275/* This function propagates processes from frontend <from> to backend <to> so
7276 * that it is always guaranteed that a backend pointed to by a frontend is
7277 * bound to all of its processes. After that, if the target is a "listen"
7278 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007279 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007280 * checked first to ensure that <to> is already bound to all processes of
7281 * <from>, there is no risk of looping and we ensure to follow the shortest
7282 * path to the destination.
7283 *
7284 * It is possible to set <to> to NULL for the first call so that the function
7285 * takes care of visiting the initial frontend in <from>.
7286 *
7287 * It is important to note that the function relies on the fact that all names
7288 * have already been resolved.
7289 */
7290void propagate_processes(struct proxy *from, struct proxy *to)
7291{
7292 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007293
7294 if (to) {
7295 /* check whether we need to go down */
7296 if (from->bind_proc &&
7297 (from->bind_proc & to->bind_proc) == from->bind_proc)
7298 return;
7299
7300 if (!from->bind_proc && !to->bind_proc)
7301 return;
7302
7303 to->bind_proc = from->bind_proc ?
7304 (to->bind_proc | from->bind_proc) : 0;
7305
7306 /* now propagate down */
7307 from = to;
7308 }
7309
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007310 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007311 return;
7312
Willy Tarreauf6b70012014-12-18 14:00:43 +01007313 if (from->state == PR_STSTOPPED)
7314 return;
7315
Willy Tarreau64ab6072014-09-16 12:17:36 +02007316 /* default_backend */
7317 if (from->defbe.be)
7318 propagate_processes(from, from->defbe.be);
7319
7320 /* use_backend */
7321 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007322 if (rule->dynamic)
7323 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324 to = rule->be.backend;
7325 propagate_processes(from, to);
7326 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007327}
7328
Willy Tarreaubb925012009-07-23 13:36:36 +02007329/*
7330 * Returns the error code, 0 if OK, or any combination of :
7331 * - ERR_ABORT: must abort ASAP
7332 * - ERR_FATAL: we can continue parsing but not start the service
7333 * - ERR_WARN: a warning has been emitted
7334 * - ERR_ALERT: an alert has been emitted
7335 * Only the two first ones can stop processing, the two others are just
7336 * indicators.
7337 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007338int check_config_validity()
7339{
7340 int cfgerr = 0;
7341 struct proxy *curproxy = NULL;
7342 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007343 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007344 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007345 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007346 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007347
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007348 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007349 /*
7350 * Now, check for the integrity of all that we have collected.
7351 */
7352
7353 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007354 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007355
Willy Tarreau193b8c62012-11-22 00:17:38 +01007356 if (!global.tune.max_http_hdr)
7357 global.tune.max_http_hdr = MAX_HTTP_HDR;
7358
7359 if (!global.tune.cookie_len)
7360 global.tune.cookie_len = CAPTURE_LEN;
7361
7362 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7363
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007364 /* Post initialisation of the users and groups lists. */
7365 err_code = userlist_postinit();
7366 if (err_code != ERR_NONE)
7367 goto out;
7368
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007369 /* first, we will invert the proxy list order */
7370 curproxy = NULL;
7371 while (proxy) {
7372 struct proxy *next;
7373
7374 next = proxy->next;
7375 proxy->next = curproxy;
7376 curproxy = proxy;
7377 if (!next)
7378 break;
7379 proxy = next;
7380 }
7381
Willy Tarreau419ead82014-09-16 13:41:21 +02007382 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007383 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007384 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007385 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007386 struct act_rule *trule;
7387 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007388 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007389 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007390 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007391
Willy Tarreau050536d2012-10-04 08:47:34 +02007392 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007393 /* proxy ID not set, use automatic numbering with first
7394 * spare entry starting with next_pxid.
7395 */
7396 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7397 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7398 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007399 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007400 next_pxid++;
7401
Willy Tarreau55ea7572007-06-17 19:56:27 +02007402
Willy Tarreaubaaee002006-06-26 02:48:02 +02007403 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007404 /* ensure we don't keep listeners uselessly bound */
7405 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007406 free((void *)curproxy->table.peers.name);
7407 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007408 continue;
7409 }
7410
Willy Tarreau102df612014-05-07 23:56:38 +02007411 /* Check multi-process mode compatibility for the current proxy */
7412
7413 if (curproxy->bind_proc) {
7414 /* an explicit bind-process was specified, let's check how many
7415 * processes remain.
7416 */
David Carliere6c39412015-07-02 07:00:17 +00007417 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007418
7419 curproxy->bind_proc &= nbits(global.nbproc);
7420 if (!curproxy->bind_proc && nbproc == 1) {
7421 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);
7422 curproxy->bind_proc = 1;
7423 }
7424 else if (!curproxy->bind_proc && nbproc > 1) {
7425 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);
7426 curproxy->bind_proc = 0;
7427 }
7428 }
7429
Willy Tarreau3d209582014-05-09 17:06:11 +02007430 /* check and reduce the bind-proc of each listener */
7431 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7432 unsigned long mask;
7433
7434 if (!bind_conf->bind_proc)
7435 continue;
7436
7437 mask = nbits(global.nbproc);
7438 if (curproxy->bind_proc)
7439 mask &= curproxy->bind_proc;
7440 /* mask cannot be null here thanks to the previous checks */
7441
David Carliere6c39412015-07-02 07:00:17 +00007442 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007443 bind_conf->bind_proc &= mask;
7444
7445 if (!bind_conf->bind_proc && nbproc == 1) {
7446 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",
7447 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7448 bind_conf->bind_proc = mask & ~(mask - 1);
7449 }
7450 else if (!bind_conf->bind_proc && nbproc > 1) {
7451 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",
7452 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7453 bind_conf->bind_proc = 0;
7454 }
7455 }
7456
Willy Tarreauff01a212009-03-15 13:46:16 +01007457 switch (curproxy->mode) {
7458 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007459 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007460 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007461 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7462 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007463 cfgerr++;
7464 }
7465
7466 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007467 Warning("config : servers will be ignored for %s '%s'.\n",
7468 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007469 break;
7470
7471 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007472 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007473 break;
7474
7475 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007476 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007477 break;
7478 }
7479
Willy Tarreauf3934b82015-08-11 11:36:45 +02007480 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7481 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7482 proxy_type_str(curproxy), curproxy->id);
7483 err_code |= ERR_WARN;
7484 }
7485
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007486 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007487 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007488 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007489 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7490 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007491 cfgerr++;
7492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007493#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007494 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007495 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7496 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007497 cfgerr++;
7498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007499#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007500 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007501 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7502 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007503 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007504 }
7505 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007506 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007507 /* If no LB algo is set in a backend, and we're not in
7508 * transparent mode, dispatch mode nor proxy mode, we
7509 * want to use balance roundrobin by default.
7510 */
7511 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7512 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007513 }
7514 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007515
Willy Tarreau1620ec32011-08-06 17:05:02 +02007516 if (curproxy->options & PR_O_DISPATCH)
7517 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7518 else if (curproxy->options & PR_O_HTTP_PROXY)
7519 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7520 else if (curproxy->options & PR_O_TRANSP)
7521 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007522
Willy Tarreau1620ec32011-08-06 17:05:02 +02007523 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7524 if (curproxy->options & PR_O_DISABLE404) {
7525 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7526 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7527 err_code |= ERR_WARN;
7528 curproxy->options &= ~PR_O_DISABLE404;
7529 }
7530 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7531 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7532 "send-state", proxy_type_str(curproxy), curproxy->id);
7533 err_code |= ERR_WARN;
7534 curproxy->options &= ~PR_O2_CHK_SNDST;
7535 }
Willy Tarreauef781042010-01-27 11:53:01 +01007536 }
7537
Simon Horman98637e52014-06-20 12:30:16 +09007538 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7539 if (!global.external_check) {
7540 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7541 curproxy->id, "option external-check");
7542 cfgerr++;
7543 }
7544 if (!curproxy->check_command) {
7545 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7546 curproxy->id, "option external-check");
7547 cfgerr++;
7548 }
7549 }
7550
Simon Horman64e34162015-02-06 11:11:57 +09007551 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007552 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7553 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007554 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7555 "'email-alert myhostname', or 'email-alert to' "
7556 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007557 "to be present).\n",
7558 proxy_type_str(curproxy), curproxy->id);
7559 err_code |= ERR_WARN;
7560 free_email_alert(curproxy);
7561 }
7562 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007563 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007564 }
7565
Simon Horman98637e52014-06-20 12:30:16 +09007566 if (curproxy->check_command) {
7567 int clear = 0;
7568 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7569 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7570 "external-check command", proxy_type_str(curproxy), curproxy->id);
7571 err_code |= ERR_WARN;
7572 clear = 1;
7573 }
7574 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007575 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007576 curproxy->id, "external-check command");
7577 cfgerr++;
7578 }
7579 if (clear) {
7580 free(curproxy->check_command);
7581 curproxy->check_command = NULL;
7582 }
7583 }
7584
7585 if (curproxy->check_path) {
7586 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7587 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7588 "external-check path", proxy_type_str(curproxy), curproxy->id);
7589 err_code |= ERR_WARN;
7590 free(curproxy->check_path);
7591 curproxy->check_path = NULL;
7592 }
7593 }
7594
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007595 /* if a default backend was specified, let's find it */
7596 if (curproxy->defbe.name) {
7597 struct proxy *target;
7598
Willy Tarreauafb39922015-05-26 12:04:09 +02007599 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007600 if (!target) {
7601 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7602 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007603 cfgerr++;
7604 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007605 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7606 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007607 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007608 } else if (target->mode != curproxy->mode &&
7609 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7610
7611 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7612 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7613 curproxy->conf.file, curproxy->conf.line,
7614 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7615 target->conf.file, target->conf.line);
7616 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007617 } else {
7618 free(curproxy->defbe.name);
7619 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007620 /* Update tot_fe_maxconn for a further fullconn's computation */
7621 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007622 /* Emit a warning if this proxy also has some servers */
7623 if (curproxy->srv) {
7624 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7625 curproxy->id);
7626 err_code |= ERR_WARN;
7627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007628 }
7629 }
7630
Emeric Brun3f783572017-01-12 11:21:28 +01007631 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7632 /* Case of listen without default backend
7633 * The curproxy will be its own default backend
7634 * so we update tot_fe_maxconn for a further
7635 * fullconn's computation */
7636 curproxy->tot_fe_maxconn += curproxy->maxconn;
7637 }
7638
Willy Tarreau55ea7572007-06-17 19:56:27 +02007639 /* find the target proxy for 'use_backend' rules */
7640 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007641 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007642 struct logformat_node *node;
7643 char *pxname;
7644
7645 /* Try to parse the string as a log format expression. If the result
7646 * of the parsing is only one entry containing a simple string, then
7647 * it's a standard string corresponding to a static rule, thus the
7648 * parsing is cancelled and be.name is restored to be resolved.
7649 */
7650 pxname = rule->be.name;
7651 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007652 curproxy->conf.args.ctx = ARGC_UBK;
7653 curproxy->conf.args.file = rule->file;
7654 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007655 err = NULL;
7656 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7657 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7658 rule->file, rule->line, pxname, err);
7659 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007660 cfgerr++;
7661 continue;
7662 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007663 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7664
7665 if (!LIST_ISEMPTY(&rule->be.expr)) {
7666 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7667 rule->dynamic = 1;
7668 free(pxname);
7669 continue;
7670 }
7671 /* simple string: free the expression and fall back to static rule */
7672 free(node->arg);
7673 free(node);
7674 }
7675
7676 rule->dynamic = 0;
7677 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007678
Willy Tarreauafb39922015-05-26 12:04:09 +02007679 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007680 if (!target) {
7681 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7682 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007683 cfgerr++;
7684 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007685 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7686 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007687 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007688 } else if (target->mode != curproxy->mode &&
7689 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7690
7691 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7692 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7693 curproxy->conf.file, curproxy->conf.line,
7694 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7695 target->conf.file, target->conf.line);
7696 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007697 } else {
7698 free((void *)rule->be.name);
7699 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007700 /* For each target of switching rules, we update
7701 * their tot_fe_maxconn, except if a previous rule point
7702 * on the same backend or on the default backend */
7703 if (rule->be.backend != curproxy->defbe.be) {
7704 struct switching_rule *swrule;
7705
7706 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7707 if (rule == swrule) {
7708 target->tot_fe_maxconn += curproxy->maxconn;
7709 break;
7710 }
7711 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7712 /* there is multiple ref of this backend */
7713 break;
7714 }
7715 }
7716 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007717 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007718 }
7719
Willy Tarreau64ab6072014-09-16 12:17:36 +02007720 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007721 list_for_each_entry(srule, &curproxy->server_rules, list) {
7722 struct server *target = findserver(curproxy, srule->srv.name);
7723
7724 if (!target) {
7725 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7726 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7727 cfgerr++;
7728 continue;
7729 }
7730 free((void *)srule->srv.name);
7731 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007732 }
7733
Emeric Brunb982a3d2010-01-04 15:45:53 +01007734 /* find the target table for 'stick' rules */
7735 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7736 struct proxy *target;
7737
Emeric Brun1d33b292010-01-04 15:47:17 +01007738 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7739 if (mrule->flags & STK_IS_STORE)
7740 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7741
Emeric Brunb982a3d2010-01-04 15:45:53 +01007742 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007743 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007744 else
7745 target = curproxy;
7746
7747 if (!target) {
7748 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7749 curproxy->id, mrule->table.name);
7750 cfgerr++;
7751 }
7752 else if (target->table.size == 0) {
7753 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7754 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7755 cfgerr++;
7756 }
Willy Tarreau12785782012-04-27 21:37:17 +02007757 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7758 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007759 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7760 cfgerr++;
7761 }
7762 else {
7763 free((void *)mrule->table.name);
7764 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007765 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007766 }
7767 }
7768
7769 /* find the target table for 'store response' rules */
7770 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7771 struct proxy *target;
7772
Emeric Brun1d33b292010-01-04 15:47:17 +01007773 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7774
Emeric Brunb982a3d2010-01-04 15:45:53 +01007775 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007776 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007777 else
7778 target = curproxy;
7779
7780 if (!target) {
7781 Alert("Proxy '%s': unable to find store table '%s'.\n",
7782 curproxy->id, mrule->table.name);
7783 cfgerr++;
7784 }
7785 else if (target->table.size == 0) {
7786 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7787 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7788 cfgerr++;
7789 }
Willy Tarreau12785782012-04-27 21:37:17 +02007790 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7791 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007792 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7793 cfgerr++;
7794 }
7795 else {
7796 free((void *)mrule->table.name);
7797 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007798 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007799 }
7800 }
7801
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007802 /* find the target table for 'tcp-request' layer 4 rules */
7803 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7804 struct proxy *target;
7805
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007806 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007807 continue;
7808
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007809 if (trule->arg.trk_ctr.table.n)
7810 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007811 else
7812 target = curproxy;
7813
7814 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007815 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007816 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007817 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007818 cfgerr++;
7819 }
7820 else if (target->table.size == 0) {
7821 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007822 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007823 cfgerr++;
7824 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007825 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007826 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007827 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007828 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007829 cfgerr++;
7830 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007831 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007832 free(trule->arg.trk_ctr.table.n);
7833 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007834 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007835 * to pass a list of counters to track and allocate them right here using
7836 * stktable_alloc_data_type().
7837 */
7838 }
7839 }
7840
Willy Tarreau620408f2016-10-21 16:37:51 +02007841 /* find the target table for 'tcp-request' layer 5 rules */
7842 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7843 struct proxy *target;
7844
7845 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7846 continue;
7847
7848 if (trule->arg.trk_ctr.table.n)
7849 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7850 else
7851 target = curproxy;
7852
7853 if (!target) {
7854 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7855 curproxy->id, trule->arg.trk_ctr.table.n,
7856 tcp_trk_idx(trule->action));
7857 cfgerr++;
7858 }
7859 else if (target->table.size == 0) {
7860 Alert("Proxy '%s': table '%s' used but not configured.\n",
7861 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7862 cfgerr++;
7863 }
7864 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7865 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7866 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7867 tcp_trk_idx(trule->action));
7868 cfgerr++;
7869 }
7870 else {
7871 free(trule->arg.trk_ctr.table.n);
7872 trule->arg.trk_ctr.table.t = &target->table;
7873 /* Note: if we decide to enhance the track-sc syntax, we may be able
7874 * to pass a list of counters to track and allocate them right here using
7875 * stktable_alloc_data_type().
7876 */
7877 }
7878 }
7879
Willy Tarreaud1f96522010-08-03 19:34:32 +02007880 /* find the target table for 'tcp-request' layer 6 rules */
7881 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7882 struct proxy *target;
7883
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007884 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007885 continue;
7886
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007887 if (trule->arg.trk_ctr.table.n)
7888 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007889 else
7890 target = curproxy;
7891
7892 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007893 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007894 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007895 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007896 cfgerr++;
7897 }
7898 else if (target->table.size == 0) {
7899 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007900 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007901 cfgerr++;
7902 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007903 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007904 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007905 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007906 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007907 cfgerr++;
7908 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007909 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007910 free(trule->arg.trk_ctr.table.n);
7911 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007912 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007913 * to pass a list of counters to track and allocate them right here using
7914 * stktable_alloc_data_type().
7915 */
7916 }
7917 }
7918
Baptiste Assmanne9544932015-11-03 23:31:35 +01007919 /* parse http-request capture rules to ensure id really exists */
7920 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7921 if (hrqrule->action != ACT_CUSTOM ||
7922 hrqrule->action_ptr != http_action_req_capture_by_id)
7923 continue;
7924
7925 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7926 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7927 curproxy->id, hrqrule->arg.capid.idx);
7928 cfgerr++;
7929 }
7930 }
7931
7932 /* parse http-response capture rules to ensure id really exists */
7933 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7934 if (hrqrule->action != ACT_CUSTOM ||
7935 hrqrule->action_ptr != http_action_res_capture_by_id)
7936 continue;
7937
7938 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7939 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7940 curproxy->id, hrqrule->arg.capid.idx);
7941 cfgerr++;
7942 }
7943 }
7944
Willy Tarreau09448f72014-06-25 18:12:15 +02007945 /* find the target table for 'http-request' layer 7 rules */
7946 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7947 struct proxy *target;
7948
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007949 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007950 continue;
7951
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007952 if (hrqrule->arg.trk_ctr.table.n)
7953 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007954 else
7955 target = curproxy;
7956
7957 if (!target) {
7958 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007959 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007960 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007961 cfgerr++;
7962 }
7963 else if (target->table.size == 0) {
7964 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007965 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007966 cfgerr++;
7967 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007968 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007969 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007970 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007971 http_trk_idx(hrqrule->action));
7972 cfgerr++;
7973 }
7974 else {
7975 free(hrqrule->arg.trk_ctr.table.n);
7976 hrqrule->arg.trk_ctr.table.t = &target->table;
7977 /* Note: if we decide to enhance the track-sc syntax, we may be able
7978 * to pass a list of counters to track and allocate them right here using
7979 * stktable_alloc_data_type().
7980 */
7981 }
7982 }
7983
7984 /* find the target table for 'http-response' layer 7 rules */
7985 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7986 struct proxy *target;
7987
7988 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7989 continue;
7990
7991 if (hrqrule->arg.trk_ctr.table.n)
7992 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7993 else
7994 target = curproxy;
7995
7996 if (!target) {
7997 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7998 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7999 http_trk_idx(hrqrule->action));
8000 cfgerr++;
8001 }
8002 else if (target->table.size == 0) {
8003 Alert("Proxy '%s': table '%s' used but not configured.\n",
8004 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8005 cfgerr++;
8006 }
8007 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8008 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8009 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8010 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008011 cfgerr++;
8012 }
8013 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008014 free(hrqrule->arg.trk_ctr.table.n);
8015 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008016 /* Note: if we decide to enhance the track-sc syntax, we may be able
8017 * to pass a list of counters to track and allocate them right here using
8018 * stktable_alloc_data_type().
8019 */
8020 }
8021 }
8022
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008023 /* move any "block" rules at the beginning of the http-request rules */
8024 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8025 /* insert block_rules into http_req_rules at the beginning */
8026 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8027 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8028 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8029 curproxy->http_req_rules.n = curproxy->block_rules.n;
8030 LIST_INIT(&curproxy->block_rules);
8031 }
8032
Emeric Brun32da3c42010-09-23 18:39:19 +02008033 if (curproxy->table.peers.name) {
8034 struct peers *curpeers = peers;
8035
8036 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8037 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8038 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008039 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008040 break;
8041 }
8042 }
8043
8044 if (!curpeers) {
8045 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8046 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008047 free((void *)curproxy->table.peers.name);
8048 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008049 cfgerr++;
8050 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008051 else if (curpeers->state == PR_STSTOPPED) {
8052 /* silently disable this peers section */
8053 curproxy->table.peers.p = NULL;
8054 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008055 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008056 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8057 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008058 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008059 cfgerr++;
8060 }
8061 }
8062
Simon Horman9dc49962015-01-30 11:22:59 +09008063
8064 if (curproxy->email_alert.mailers.name) {
8065 struct mailers *curmailers = mailers;
8066
8067 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8068 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8069 free(curproxy->email_alert.mailers.name);
8070 curproxy->email_alert.mailers.m = curmailers;
8071 curmailers->users++;
8072 break;
8073 }
8074 }
8075
8076 if (!curmailers) {
8077 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8078 curproxy->id, curproxy->email_alert.mailers.name);
8079 free_email_alert(curproxy);
8080 cfgerr++;
8081 }
8082 }
8083
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008084 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008085 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008086 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8087 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8088 "proxy", curproxy->id);
8089 cfgerr++;
8090 goto out_uri_auth_compat;
8091 }
8092
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008093 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008094 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008095 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008096 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008097
Willy Tarreau95fa4692010-02-01 13:05:50 +01008098 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8099 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008100
8101 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008102 uri_auth_compat_req[i++] = "realm";
8103 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8104 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008105
Willy Tarreau95fa4692010-02-01 13:05:50 +01008106 uri_auth_compat_req[i++] = "unless";
8107 uri_auth_compat_req[i++] = "{";
8108 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8109 uri_auth_compat_req[i++] = "}";
8110 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008111
Willy Tarreauff011f22011-01-06 17:51:27 +01008112 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8113 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008114 cfgerr++;
8115 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008116 }
8117
Willy Tarreauff011f22011-01-06 17:51:27 +01008118 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008119
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008120 if (curproxy->uri_auth->auth_realm) {
8121 free(curproxy->uri_auth->auth_realm);
8122 curproxy->uri_auth->auth_realm = NULL;
8123 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008124
8125 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008126 }
8127out_uri_auth_compat:
8128
Dragan Dosen43885c72015-10-01 13:18:13 +02008129 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008130 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008131 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8132 if (!curproxy->conf.logformat_sd_string) {
8133 /* set the default logformat_sd_string */
8134 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8135 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008136 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008137 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008138 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008139
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008140 /* compile the log format */
8141 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008142 if (curproxy->conf.logformat_string != default_http_log_format &&
8143 curproxy->conf.logformat_string != default_tcp_log_format &&
8144 curproxy->conf.logformat_string != clf_http_log_format)
8145 free(curproxy->conf.logformat_string);
8146 curproxy->conf.logformat_string = NULL;
8147 free(curproxy->conf.lfs_file);
8148 curproxy->conf.lfs_file = NULL;
8149 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008150
8151 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8152 free(curproxy->conf.logformat_sd_string);
8153 curproxy->conf.logformat_sd_string = NULL;
8154 free(curproxy->conf.lfsd_file);
8155 curproxy->conf.lfsd_file = NULL;
8156 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008157 }
8158
Willy Tarreau62a61232013-04-12 18:13:46 +02008159 if (curproxy->conf.logformat_string) {
8160 curproxy->conf.args.ctx = ARGC_LOG;
8161 curproxy->conf.args.file = curproxy->conf.lfs_file;
8162 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008163 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008164 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008165 SMP_VAL_FE_LOG_END, &err)) {
8166 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8167 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8168 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008169 cfgerr++;
8170 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008171 curproxy->conf.args.file = NULL;
8172 curproxy->conf.args.line = 0;
8173 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008174
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008175 if (curproxy->conf.logformat_sd_string) {
8176 curproxy->conf.args.ctx = ARGC_LOGSD;
8177 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8178 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008179 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008180 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 +01008181 SMP_VAL_FE_LOG_END, &err)) {
8182 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8183 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8184 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008185 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008186 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8187 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8188 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8189 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008190 cfgerr++;
8191 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008192 curproxy->conf.args.file = NULL;
8193 curproxy->conf.args.line = 0;
8194 }
8195
Willy Tarreau62a61232013-04-12 18:13:46 +02008196 if (curproxy->conf.uniqueid_format_string) {
8197 curproxy->conf.args.ctx = ARGC_UIF;
8198 curproxy->conf.args.file = curproxy->conf.uif_file;
8199 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008200 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008201 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 +01008202 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8203 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8204 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8205 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008206 cfgerr++;
8207 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008208 curproxy->conf.args.file = NULL;
8209 curproxy->conf.args.line = 0;
8210 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008211
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008212 /* only now we can check if some args remain unresolved.
8213 * This must be done after the users and groups resolution.
8214 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008215 cfgerr += smp_resolve_args(curproxy);
8216 if (!cfgerr)
8217 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008218
Willy Tarreau2738a142006-07-08 17:28:09 +02008219 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008220 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008221 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008222 (!curproxy->timeout.connect ||
8223 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008224 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008225 " | While not properly invalid, you will certainly encounter various problems\n"
8226 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008227 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008228 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008229 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008230 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008231
Willy Tarreau1fa31262007-12-03 00:36:16 +01008232 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8233 * We must still support older configurations, so let's find out whether those
8234 * parameters have been set or must be copied from contimeouts.
8235 */
8236 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008237 if (!curproxy->timeout.tarpit ||
8238 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008239 /* tarpit timeout not set. We search in the following order:
8240 * default.tarpit, curr.connect, default.connect.
8241 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008242 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008243 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008244 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008245 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008246 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008247 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008248 }
8249 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008250 (!curproxy->timeout.queue ||
8251 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008252 /* queue timeout not set. We search in the following order:
8253 * default.queue, curr.connect, default.connect.
8254 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008255 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008256 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008257 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008258 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008259 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008260 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008261 }
8262 }
8263
Willy Tarreau1620ec32011-08-06 17:05:02 +02008264 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008265 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008266 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008267 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008268 }
8269
Willy Tarreau215663d2014-06-13 18:30:23 +02008270 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8271 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8272 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8273 proxy_type_str(curproxy), curproxy->id);
8274 err_code |= ERR_WARN;
8275 }
8276
Willy Tarreau193b8c62012-11-22 00:17:38 +01008277 /* ensure that cookie capture length is not too large */
8278 if (curproxy->capture_len >= global.tune.cookie_len) {
8279 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8280 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8281 err_code |= ERR_WARN;
8282 curproxy->capture_len = global.tune.cookie_len - 1;
8283 }
8284
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008285 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008286 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008287 curproxy->req_cap_pool = create_pool("ptrcap",
8288 curproxy->nb_req_cap * sizeof(char *),
8289 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008290 }
8291
8292 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008293 curproxy->rsp_cap_pool = create_pool("ptrcap",
8294 curproxy->nb_rsp_cap * sizeof(char *),
8295 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008296 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008297
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008298 switch (curproxy->load_server_state_from_file) {
8299 case PR_SRV_STATE_FILE_UNSPEC:
8300 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8301 break;
8302 case PR_SRV_STATE_FILE_GLOBAL:
8303 if (!global.server_state_file) {
8304 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",
8305 curproxy->id);
8306 err_code |= ERR_WARN;
8307 }
8308 break;
8309 }
8310
Willy Tarreaubaaee002006-06-26 02:48:02 +02008311 /* first, we will invert the servers list order */
8312 newsrv = NULL;
8313 while (curproxy->srv) {
8314 struct server *next;
8315
8316 next = curproxy->srv->next;
8317 curproxy->srv->next = newsrv;
8318 newsrv = curproxy->srv;
8319 if (!next)
8320 break;
8321 curproxy->srv = next;
8322 }
8323
Willy Tarreau17edc812014-01-03 12:14:34 +01008324 /* Check that no server name conflicts. This causes trouble in the stats.
8325 * We only emit a warning for the first conflict affecting each server,
8326 * in order to avoid combinatory explosion if all servers have the same
8327 * name. We do that only for servers which do not have an explicit ID,
8328 * because these IDs were made also for distinguishing them and we don't
8329 * want to annoy people who correctly manage them.
8330 */
8331 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8332 struct server *other_srv;
8333
8334 if (newsrv->puid)
8335 continue;
8336
8337 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8338 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8339 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8340 newsrv->conf.file, newsrv->conf.line,
8341 proxy_type_str(curproxy), curproxy->id,
8342 newsrv->id, other_srv->conf.line);
8343 break;
8344 }
8345 }
8346 }
8347
Willy Tarreaudd701652010-05-25 23:03:02 +02008348 /* assign automatic UIDs to servers which don't have one yet */
8349 next_id = 1;
8350 newsrv = curproxy->srv;
8351 while (newsrv != NULL) {
8352 if (!newsrv->puid) {
8353 /* server ID not set, use automatic numbering with first
8354 * spare entry starting with next_svid.
8355 */
8356 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8357 newsrv->conf.id.key = newsrv->puid = next_id;
8358 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8359 }
8360 next_id++;
8361 newsrv = newsrv->next;
8362 }
8363
Willy Tarreau20697042007-11-15 23:26:18 +01008364 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008365 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008366
Willy Tarreau62c3be22012-01-20 13:12:32 +01008367 /*
8368 * If this server supports a maxconn parameter, it needs a dedicated
8369 * tasks to fill the emptied slots when a connection leaves.
8370 * Also, resolve deferred tracking dependency if needed.
8371 */
8372 newsrv = curproxy->srv;
8373 while (newsrv != NULL) {
8374 if (newsrv->minconn > newsrv->maxconn) {
8375 /* Only 'minconn' was specified, or it was higher than or equal
8376 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8377 * this will avoid further useless expensive computations.
8378 */
8379 newsrv->maxconn = newsrv->minconn;
8380 } else if (newsrv->maxconn && !newsrv->minconn) {
8381 /* minconn was not specified, so we set it to maxconn */
8382 newsrv->minconn = newsrv->maxconn;
8383 }
8384
Willy Tarreau17d45382016-12-22 21:16:08 +01008385 /* this will also properly set the transport layer for prod and checks */
8386 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8387 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8388 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8389 }
Emeric Brun94324a42012-10-11 14:00:19 +02008390
Willy Tarreau2f075e92013-12-03 11:11:34 +01008391 /* set the check type on the server */
8392 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8393
Willy Tarreau62c3be22012-01-20 13:12:32 +01008394 if (newsrv->trackit) {
8395 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008396 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008397 char *pname, *sname;
8398
8399 pname = newsrv->trackit;
8400 sname = strrchr(pname, '/');
8401
8402 if (sname)
8403 *sname++ = '\0';
8404 else {
8405 sname = pname;
8406 pname = NULL;
8407 }
8408
8409 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008410 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008411 if (!px) {
8412 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8413 proxy_type_str(curproxy), curproxy->id,
8414 newsrv->id, pname);
8415 cfgerr++;
8416 goto next_srv;
8417 }
8418 } else
8419 px = curproxy;
8420
8421 srv = findserver(px, sname);
8422 if (!srv) {
8423 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8424 proxy_type_str(curproxy), curproxy->id,
8425 newsrv->id, sname);
8426 cfgerr++;
8427 goto next_srv;
8428 }
8429
Willy Tarreau32091232014-05-16 13:52:00 +02008430 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8431 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8432 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008433 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008434 "tracking as it does not have any check nor agent enabled.\n",
8435 proxy_type_str(curproxy), curproxy->id,
8436 newsrv->id, px->id, srv->id);
8437 cfgerr++;
8438 goto next_srv;
8439 }
8440
8441 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8442
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008443 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008444 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8445 "belongs to a tracking chain looping back to %s/%s.\n",
8446 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008447 newsrv->id, px->id, srv->id, px->id,
8448 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008449 cfgerr++;
8450 goto next_srv;
8451 }
8452
8453 if (curproxy != px &&
8454 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8455 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8456 "tracking: disable-on-404 option inconsistency.\n",
8457 proxy_type_str(curproxy), curproxy->id,
8458 newsrv->id, px->id, srv->id);
8459 cfgerr++;
8460 goto next_srv;
8461 }
8462
Willy Tarreau62c3be22012-01-20 13:12:32 +01008463 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008464 newsrv->tracknext = srv->trackers;
8465 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008466
8467 free(newsrv->trackit);
8468 newsrv->trackit = NULL;
8469 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008470
8471 /*
8472 * resolve server's resolvers name and update the resolvers pointer
8473 * accordingly
8474 */
8475 if (newsrv->resolvers_id) {
8476 struct dns_resolvers *curr_resolvers;
8477 int found;
8478
8479 found = 0;
8480 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8481 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8482 found = 1;
8483 break;
8484 }
8485 }
8486
8487 if (!found) {
8488 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8489 proxy_type_str(curproxy), curproxy->id,
8490 newsrv->id, newsrv->resolvers_id);
8491 cfgerr++;
8492 } else {
8493 free(newsrv->resolvers_id);
8494 newsrv->resolvers_id = NULL;
8495 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 */