blob: bafd05133d4c21f9c1c0566ea6aa38fc6f69568d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
William Lallemand9ed62032016-11-21 17:49:11 +010062#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020063#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020064#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020065#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020066#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010067#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020068#include <proto/lb_fwlc.h>
69#include <proto/lb_fwrr.h>
70#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020071#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010074#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020075#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010083#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010084#include <proto/task.h>
85#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
87
Willy Tarreauf3c69202006-07-09 16:42:34 +020088/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
89 * ssl-hello-chk option to ensure that the remote server speaks SSL.
90 *
91 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
92 */
93const char sslv3_client_hello_pkt[] = {
94 "\x16" /* ContentType : 0x16 = Hanshake */
95 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
96 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
97 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
98 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
99 "\x03\x00" /* Hello Version : 0x0300 = v3 */
100 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
101 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
102 "\x00" /* Session ID length : empty (no session ID) */
103 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
104 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
105 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
106 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
107 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
108 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
109 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
110 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
111 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
112 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
113 "\x00\x38" "\x00\x39" "\x00\x3A"
114 "\x01" /* Compression Length : 0x01 = 1 byte for types */
115 "\x00" /* Compression Type : 0x00 = NULL compression */
116};
117
Willy Tarreau3842f002009-06-14 11:39:52 +0200118/* various keyword modifiers */
119enum kw_mod {
120 KWM_STD = 0, /* normal */
121 KWM_NO, /* "no" prefixed before the keyword */
122 KWM_DEF, /* "default" prefixed before the keyword */
123};
124
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100125/* permit to store configuration section */
126struct cfg_section {
127 struct list list;
128 char *section_name;
129 int (*section_parser)(const char *, int, char **, int);
130};
131
132/* Used to chain configuration sections definitions. This list
133 * stores struct cfg_section
134 */
135struct list sections = LIST_HEAD_INIT(sections);
136
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100138struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139 const char *name;
140 unsigned int val;
141 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100142 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144};
145
146/* proxy->options */
147static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
150 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
151 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
152 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
153 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
154 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200156 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200157 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100158 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
160 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
161 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100163#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100165#else
166 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100167#endif
168
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100170};
171
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100172/* proxy->options2 */
173static const struct cfg_opt cfg_opts2[] =
174{
175#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
177 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100179#else
180 { "splice-request", 0, 0, 0, 0 },
181 { "splice-response", 0, 0, 0, 0 },
182 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100183#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100184 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
185 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
186 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
187 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
188 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
189 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
190 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
192 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400193 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100194 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200195 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200196 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100197 { NULL, 0, 0, 0 }
198};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199
Willy Tarreau6daf3432008-01-22 16:44:08 +0100200static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
202int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100203int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100204char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200206/* List head of all known configuration keywords */
207static struct cfg_kw_list cfg_keywords = {
208 .list = LIST_HEAD_INIT(cfg_keywords.list)
209};
210
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211/*
212 * converts <str> to a list of listeners which are dynamically allocated.
213 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
214 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
215 * - <port> is a numerical port from 1 to 65535 ;
216 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
217 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
219 * not NULL, it must be a valid pointer to either NULL or a freeable area that
220 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223{
224 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 int port, end;
227
228 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200229
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100232 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
234 str = next;
235 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100236 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 *next++ = 0;
238 }
239
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100240 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200241 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200242 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 if (!ss2)
244 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port || !end) {
253 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
254 goto fail;
255 }
256
Emeric Bruned760922010-10-22 17:59:25 +0200257 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
261
262 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100267 else if (ss2->ss_family == AF_UNSPEC) {
268 socklen_t addr_len;
269
270 /* We want to attach to an already bound fd whose number
271 * is in the addr part of ss2 when cast to sockaddr_in.
272 * Note that by definition there is a single listener.
273 * We still have to determine the address family to
274 * register the correct protocol.
275 */
276 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
277 addr_len = sizeof(*ss2);
278 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
279 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
280 goto fail;
281 }
282
283 port = end = get_host_port(ss2);
284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100286 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200287 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100288
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200290 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100291 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200292 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
293 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200294 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau40aa0702013-03-10 23:51:38 +0100296 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200297 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100298 l->state = LI_INIT;
299
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100300 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100302 tcpv4_add_listener(l);
303 }
Emeric Bruned760922010-10-22 17:59:25 +0200304 else if (ss.ss_family == AF_INET6) {
305 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
306 tcpv6_add_listener(l);
307 }
308 else {
Emeric Bruned760922010-10-22 17:59:25 +0200309 uxst_add_listener(l);
310 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200311
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200312 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100313 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200314 } /* end for(port) */
315 } /* end while(next) */
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 fail:
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321}
322
William Lallemand6e62fb62015-04-28 16:55:23 +0200323/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100324 * Report an error in <msg> when there are too many arguments. This version is
325 * intended to be used by keyword parsers so that the message will be included
326 * into the general error message. The index is the current keyword in args.
327 * Return 0 if the number of argument is correct, otherwise build a message and
328 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
329 * message may also be null, it will simply not be produced (useful to check only).
330 * <msg> and <err_code> are only affected on error.
331 */
332int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
333{
334 int i;
335
336 if (!*args[index + maxarg + 1])
337 return 0;
338
339 if (msg) {
340 *msg = NULL;
341 memprintf(msg, "%s", args[0]);
342 for (i = 1; i <= index; i++)
343 memprintf(msg, "%s %s", *msg, args[i]);
344
345 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
346 }
347 if (err_code)
348 *err_code |= ERR_ALERT | ERR_FATAL;
349
350 return 1;
351}
352
353/*
354 * same as too_many_args_idx with a 0 index
355 */
356int too_many_args(int maxarg, char **args, char **msg, int *err_code)
357{
358 return too_many_args_idx(maxarg, 0, args, msg, err_code);
359}
360
361/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200362 * Report a fatal Alert when there is too much arguments
363 * The index is the current keyword in args
364 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
365 * Fill err_code with an ERR_ALERT and an ERR_FATAL
366 */
367int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
368{
369 char *kw = NULL;
370 int i;
371
372 if (!*args[index + maxarg + 1])
373 return 0;
374
375 memprintf(&kw, "%s", args[0]);
376 for (i = 1; i <= index; i++) {
377 memprintf(&kw, "%s %s", kw, args[i]);
378 }
379
380 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
381 free(kw);
382 *err_code |= ERR_ALERT | ERR_FATAL;
383 return 1;
384}
385
386/*
387 * same as alertif_too_many_args_idx with a 0 index
388 */
389int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
390{
391 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
392}
393
Willy Tarreau620408f2016-10-21 16:37:51 +0200394/* Report a warning if a rule is placed after a 'tcp-request session' rule.
395 * Return 1 if the warning has been emitted, otherwise 0.
396 */
397int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
398{
399 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
400 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
401 file, line, arg);
402 return 1;
403 }
404 return 0;
405}
406
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200407/* Report a warning if a rule is placed after a 'tcp-request content' rule.
408 * Return 1 if the warning has been emitted, otherwise 0.
409 */
410int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
411{
412 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
413 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
414 file, line, arg);
415 return 1;
416 }
417 return 0;
418}
419
Willy Tarreau61d18892009-03-31 10:49:21 +0200420/* Report a warning if a rule is placed after a 'block' rule.
421 * Return 1 if the warning has been emitted, otherwise 0.
422 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200425 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200426 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
427 file, line, arg);
428 return 1;
429 }
430 return 0;
431}
432
Willy Tarreau5002f572014-04-23 01:32:02 +0200433/* Report a warning if a rule is placed after an 'http_request' rule.
434 * Return 1 if the warning has been emitted, otherwise 0.
435 */
436int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
437{
438 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
439 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
440 file, line, arg);
441 return 1;
442 }
443 return 0;
444}
445
Willy Tarreau61d18892009-03-31 10:49:21 +0200446/* Report a warning if a rule is placed after a reqrewrite rule.
447 * Return 1 if the warning has been emitted, otherwise 0.
448 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100449int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200450{
451 if (proxy->req_exp) {
452 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
453 file, line, arg);
454 return 1;
455 }
456 return 0;
457}
458
459/* Report a warning if a rule is placed after a reqadd rule.
460 * Return 1 if the warning has been emitted, otherwise 0.
461 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100462int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200463{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100464 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200465 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
466 file, line, arg);
467 return 1;
468 }
469 return 0;
470}
471
472/* Report a warning if a rule is placed after a redirect rule.
473 * Return 1 if the warning has been emitted, otherwise 0.
474 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
478 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
479 file, line, arg);
480 return 1;
481 }
482 return 0;
483}
484
485/* Report a warning if a rule is placed after a 'use_backend' rule.
486 * Return 1 if the warning has been emitted, otherwise 0.
487 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100488int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200489{
490 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
491 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
492 file, line, arg);
493 return 1;
494 }
495 return 0;
496}
497
Willy Tarreauee445d92014-04-23 01:39:04 +0200498/* Report a warning if a rule is placed after a 'use-server' rule.
499 * Return 1 if the warning has been emitted, otherwise 0.
500 */
501int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
502{
503 if (!LIST_ISEMPTY(&proxy->server_rules)) {
504 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
505 file, line, arg);
506 return 1;
507 }
508 return 0;
509}
510
Willy Tarreaud39ad442016-11-25 15:16:12 +0100511/* report a warning if a redirect rule is dangerously placed */
512int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200513{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100514 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200515 warnif_rule_after_use_server(proxy, file, line, arg);
516}
517
Willy Tarreaud39ad442016-11-25 15:16:12 +0100518/* report a warning if a reqadd rule is dangerously placed */
519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200520{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
522 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200523}
524
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525/* report a warning if a reqxxx rule is dangerously placed */
526int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200527{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100528 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
529 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200530}
531
532/* report a warning if an http-request rule is dangerously placed */
533int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
534{
Willy Tarreau61d18892009-03-31 10:49:21 +0200535 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100536 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200537}
538
Willy Tarreaud39ad442016-11-25 15:16:12 +0100539/* report a warning if a block rule is dangerously placed */
540int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200541{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542 return warnif_rule_after_http_req(proxy, file, line, arg) ||
543 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200544}
545
Willy Tarreaud39ad442016-11-25 15:16:12 +0100546/* report a warning if a "tcp request content" rule is dangerously placed */
547int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200548{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100549 return warnif_rule_after_block(proxy, file, line, arg) ||
550 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200551}
552
Willy Tarreaud39ad442016-11-25 15:16:12 +0100553/* report a warning if a "tcp request session" rule is dangerously placed */
554int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200555{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100556 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
557 warnif_misplaced_tcp_cont(proxy, file, line, arg);
558}
559
560/* report a warning if a "tcp request connection" rule is dangerously placed */
561int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
562{
563 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
564 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200565}
566
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100567/* Report it if a request ACL condition uses some keywords that are incompatible
568 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
569 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
570 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100571 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100572static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100573{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100574 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200575 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100576
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100577 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100578 return 0;
579
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100580 acl = acl_cond_conflicts(cond, where);
581 if (acl) {
582 if (acl->name && *acl->name)
583 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
584 file, line, acl->name, sample_ckp_names(where));
585 else
586 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200587 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100588 return ERR_WARN;
589 }
590 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100591 return 0;
592
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100593 if (acl->name && *acl->name)
594 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200595 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100596 else
597 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200598 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100599 return ERR_WARN;
600}
601
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200603 * parse a line in a <global> section. Returns the error code, 0 if OK, or
604 * any combination of :
605 * - ERR_ABORT: must abort ASAP
606 * - ERR_FATAL: we can continue parsing but not start the service
607 * - ERR_WARN: a warning has been emitted
608 * - ERR_ALERT: an alert has been emitted
609 * Only the two first ones can stop processing, the two others are just
610 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200612int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613{
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200615 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616
617 if (!strcmp(args[0], "global")) { /* new section */
618 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200619 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 }
622 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200623 if (alertif_too_many_args(0, file, linenum, args, &err_code))
624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 global.mode |= MODE_DAEMON;
626 }
627 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200628 if (alertif_too_many_args(0, file, linenum, args, &err_code))
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 global.mode |= MODE_DEBUG;
631 }
632 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100635 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200637 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100640 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100647 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100650 global.tune.options &= ~GTUNE_USE_SPLICE;
651 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200652 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200655 global.tune.options &= ~GTUNE_USE_GAI;
656 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000657 else if (!strcmp(args[0], "noreuseport")) {
658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
660 global.tune.options &= ~GTUNE_USE_REUSEPORT;
661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 global.mode |= MODE_QUIET;
666 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200667 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(1, file, linenum, args, &err_code))
669 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 if (global.tune.maxpollevents != 0) {
671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT;
673 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200674 }
675 if (*(args[1]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 global.tune.maxpollevents = atol(args[1]);
681 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100682 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 if (global.tune.maxaccept != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 global.tune.maxaccept = atol(args[1]);
696 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200697 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.chksize = atol(args[1]);
706 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100707 else if (!strcmp(args[0], "tune.recv_enough")) {
708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
709 goto out;
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 global.tune.recv_enough = atol(args[1]);
716 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100717 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
719 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100720 if (*(args[1]) == 0) {
721 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
722 err_code |= ERR_ALERT | ERR_FATAL;
723 goto out;
724 }
725 global.tune.buf_limit = atol(args[1]);
726 if (global.tune.buf_limit) {
727 if (global.tune.buf_limit < 3)
728 global.tune.buf_limit = 3;
729 if (global.tune.buf_limit <= global.tune.reserved_bufs)
730 global.tune.buf_limit = global.tune.reserved_bufs + 1;
731 }
732 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100733 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741 global.tune.reserved_bufs = atol(args[1]);
742 if (global.tune.reserved_bufs < 2)
743 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100744 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100746 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200747 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200756 if (global.tune.bufsize <= 0) {
757 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
760 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100761 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100762 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200763 }
764 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200765 if (alertif_too_many_args(1, file, linenum, args, &err_code))
766 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200773 if (global.tune.maxrewrite < 0) {
774 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100779 else if (!strcmp(args[0], "tune.idletimer")) {
780 unsigned int idle;
781 const char *res;
782
William Lallemand1a748ae2015-05-19 16:37:23 +0200783 if (alertif_too_many_args(1, file, linenum, args, &err_code))
784 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100785 if (*(args[1]) == 0) {
786 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790
791 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
792 if (res) {
793 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
794 file, linenum, *res, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798
799 if (idle > 65535) {
800 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.idle_timer = idle;
805 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100806 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200807 if (alertif_too_many_args(1, file, linenum, args, &err_code))
808 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100809 if (global.tune.client_rcvbuf != 0) {
810 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
811 err_code |= ERR_ALERT;
812 goto out;
813 }
814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.client_rcvbuf = atol(args[1]);
820 }
821 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.server_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.server_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.client_sndbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.client_sndbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.server_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.server_sndbuf = atol(args[1]);
865 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200866 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.tune.pipesize = atol(args[1]);
875 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100876 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200877 if (alertif_too_many_args(1, file, linenum, args, &err_code))
878 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884 global.tune.cookie_len = atol(args[1]) + 1;
885 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200886 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200887 if (alertif_too_many_args(1, file, linenum, args, &err_code))
888 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 global.tune.max_http_hdr = atol(args[1]);
895 }
William Lallemandf3747832012-11-09 12:33:10 +0100896 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
898 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100899 if (*args[1]) {
900 global.tune.comp_maxlevel = atoi(args[1]);
901 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
902 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
903 file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 } else {
908 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
909 file, linenum, args[0]);
910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
913 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200914 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
915 if (*args[1]) {
916 global.tune.pattern_cache = atoi(args[1]);
917 if (global.tune.pattern_cache < 0) {
918 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
919 file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923 } else {
924 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
925 file, linenum, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
928 }
929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200931 if (alertif_too_many_args(1, file, linenum, args, &err_code))
932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200934 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100943 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
944 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
945 err_code |= ERR_WARN;
946 goto out;
947 }
948
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200951 if (alertif_too_many_args(1, file, linenum, args, &err_code))
952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200954 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT;
956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100963 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
964 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
965 err_code |= ERR_WARN;
966 goto out;
967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
Simon Horman98637e52014-06-20 12:30:16 +0900969 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200970 if (alertif_too_many_args(0, file, linenum, args, &err_code))
971 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900972 global.external_check = 1;
973 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200974 /* user/group name handling */
975 else if (!strcmp(args[0], "user")) {
976 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200977 if (alertif_too_many_args(1, file, linenum, args, &err_code))
978 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200979 if (global.uid != 0) {
980 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT;
982 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200983 }
984 errno = 0;
985 ha_user = getpwnam(args[1]);
986 if (ha_user != NULL) {
987 global.uid = (int)ha_user->pw_uid;
988 }
989 else {
990 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200992 }
993 }
994 else if (!strcmp(args[0], "group")) {
995 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +0200996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
997 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200998 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200999 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT;
1001 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001002 }
1003 errno = 0;
1004 ha_group = getgrnam(args[1]);
1005 if (ha_group != NULL) {
1006 global.gid = (int)ha_group->gr_gid;
1007 }
1008 else {
1009 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001011 }
1012 }
1013 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001015 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 if (*(args[1]) == 0) {
1018 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001023 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1024 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1025 file, linenum, args[0], LONGBITS, global.nbproc);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 }
1030 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001031 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 if (global.maxconn != 0) {
1034 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 global.maxconn = atol(args[1]);
1044#ifdef SYSTEM_MAXCONN
1045 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1046 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1047 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
1050#endif /* SYSTEM_MAXCONN */
1051 }
Emeric Brun850efd52014-01-29 12:24:34 +01001052 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001053 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1054 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
1060 if (strcmp(args[1],"none") == 0)
1061 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1062 else if (strcmp(args[1],"required") == 0)
1063 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1064 else {
1065 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001070 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001071 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1072 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001073 if (global.cps_lim != 0) {
1074 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1075 err_code |= ERR_ALERT;
1076 goto out;
1077 }
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
1082 }
1083 global.cps_lim = atol(args[1]);
1084 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001085 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001088 if (global.sps_lim != 0) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1090 err_code |= ERR_ALERT;
1091 goto out;
1092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
1097 }
1098 global.sps_lim = atol(args[1]);
1099 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001100 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001101 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1102 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001103 if (global.ssl_lim != 0) {
1104 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1105 err_code |= ERR_ALERT;
1106 goto out;
1107 }
1108 if (*(args[1]) == 0) {
1109 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113 global.ssl_lim = atol(args[1]);
1114 }
William Lallemandd85f9172012-11-09 17:05:39 +01001115 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001116 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1117 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001118 if (*(args[1]) == 0) {
1119 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 global.comp_rate_lim = atoi(args[1]) * 1024;
1124 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001125 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001126 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1127 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001128 if (global.maxpipes != 0) {
1129 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT;
1131 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001132 }
1133 if (*(args[1]) == 0) {
1134 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001137 }
1138 global.maxpipes = atol(args[1]);
1139 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001140 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001141 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1142 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
William Lallemande3a7d992012-11-20 11:25:20 +01001148 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001149 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001150 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001151 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1152 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001153 if (*(args[1]) == 0) {
1154 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto out;
1157 }
1158 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001159 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001160 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001164 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001165
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001167 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 if (global.rlimit_nofile != 0) {
1170 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 global.rlimit_nofile = atol(args[1]);
1180 }
1181 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 if (global.chroot != NULL) {
1185 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001186 err_code |= ERR_ALERT;
1187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001188 }
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
1194 global.chroot = strdup(args[1]);
1195 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001196 else if (!strcmp(args[0], "description")) {
1197 int i, len=0;
1198 char *d;
1199
1200 if (!*args[1]) {
1201 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1202 file, linenum, args[0]);
1203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
1205 }
1206
Willy Tarreau348acfe2014-04-14 15:00:39 +02001207 for (i = 1; *args[i]; i++)
1208 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001209
1210 if (global.desc)
1211 free(global.desc);
1212
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001213 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001214
Willy Tarreau348acfe2014-04-14 15:00:39 +02001215 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1216 for (i = 2; *args[i]; i++)
1217 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001218 }
1219 else if (!strcmp(args[0], "node")) {
1220 int i;
1221 char c;
1222
William Lallemand1a748ae2015-05-19 16:37:23 +02001223 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1224 goto out;
1225
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001226 for (i=0; args[1][i]; i++) {
1227 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001228 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1229 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001230 break;
1231 }
1232
1233 if (!i || args[1][i]) {
1234 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1235 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1236 file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240
1241 if (global.node)
1242 free(global.node);
1243
1244 global.node = strdup(args[1]);
1245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001247 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 if (global.pidfile != NULL) {
1250 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001251 err_code |= ERR_ALERT;
1252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
1254 if (*(args[1]) == 0) {
1255 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 global.pidfile = strdup(args[1]);
1260 }
Emeric Bruned760922010-10-22 17:59:25 +02001261 else if (!strcmp(args[0], "unix-bind")) {
1262 int cur_arg = 1;
1263 while (*(args[cur_arg])) {
1264 if (!strcmp(args[cur_arg], "prefix")) {
1265 if (global.unix_bind.prefix != NULL) {
1266 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1267 err_code |= ERR_ALERT;
1268 cur_arg += 2;
1269 continue;
1270 }
1271
1272 if (*(args[cur_arg+1]) == 0) {
1273 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1278 cur_arg += 2;
1279 continue;
1280 }
1281
1282 if (!strcmp(args[cur_arg], "mode")) {
1283
1284 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1285 cur_arg += 2;
1286 continue;
1287 }
1288
1289 if (!strcmp(args[cur_arg], "uid")) {
1290
1291 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (!strcmp(args[cur_arg], "gid")) {
1297
1298 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (!strcmp(args[cur_arg], "user")) {
1304 struct passwd *user;
1305
1306 user = getpwnam(args[cur_arg + 1]);
1307 if (!user) {
1308 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1309 file, linenum, args[0], args[cur_arg + 1 ]);
1310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
1312 }
1313
1314 global.unix_bind.ux.uid = user->pw_uid;
1315 cur_arg += 2;
1316 continue;
1317 }
1318
1319 if (!strcmp(args[cur_arg], "group")) {
1320 struct group *group;
1321
1322 group = getgrnam(args[cur_arg + 1]);
1323 if (!group) {
1324 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1325 file, linenum, args[0], args[cur_arg + 1 ]);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329
1330 global.unix_bind.ux.gid = group->gr_gid;
1331 cur_arg += 2;
1332 continue;
1333 }
1334
Willy Tarreaub48f9582011-09-05 01:17:06 +02001335 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001336 file, linenum, args[0]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
1340 }
William Lallemand0f99e342011-10-12 17:50:54 +02001341 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1342 /* delete previous herited or defined syslog servers */
1343 struct logsrv *back;
1344 struct logsrv *tmp;
1345
1346 if (*(args[1]) != 0) {
1347 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto out;
1350 }
1351
1352 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1353 LIST_DEL(&tmp->list);
1354 free(tmp);
1355 }
1356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001358 struct sockaddr_storage *sk;
1359 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001360 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001361 int arg = 0;
1362 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001363
William Lallemand1a748ae2015-05-19 16:37:23 +02001364 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1365 goto out;
1366
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 if (*(args[1]) == 0 || *(args[2]) == 0) {
1368 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001369 err_code |= ERR_ALERT | ERR_FATAL;
1370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371 }
William Lallemand0f99e342011-10-12 17:50:54 +02001372
Vincent Bernat02779b62016-04-03 13:48:43 +02001373 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001374
Willy Tarreau18324f52014-06-27 18:10:07 +02001375 /* just after the address, a length may be specified */
1376 if (strcmp(args[arg+2], "len") == 0) {
1377 len = atoi(args[arg+3]);
1378 if (len < 80 || len > 65535) {
1379 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1380 file, linenum, args[arg+3]);
1381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
1383 }
1384 logsrv->maxlen = len;
1385
1386 /* skip these two args */
1387 arg += 2;
1388 }
1389 else
1390 logsrv->maxlen = MAX_SYSLOG_LEN;
1391
1392 if (logsrv->maxlen > global.max_syslog_len) {
1393 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001394 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1395 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1396 logline = my_realloc2(logline, global.max_syslog_len + 1);
1397 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001398 }
1399
Dragan Dosen1322d092015-09-22 16:05:32 +02001400 /* after the length, a format may be specified */
1401 if (strcmp(args[arg+2], "format") == 0) {
1402 logsrv->format = get_log_format(args[arg+3]);
1403 if (logsrv->format < 0) {
1404 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1405 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001406 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001407 goto out;
1408 }
1409
1410 /* skip these two args */
1411 arg += 2;
1412 }
1413
David Carlier97880bb2016-04-08 10:35:26 +01001414 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1415 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001416 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001417 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001418
Willy Tarreau18324f52014-06-27 18:10:07 +02001419 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001420 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001421 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001422 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001423 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001424 }
1425
William Lallemand0f99e342011-10-12 17:50:54 +02001426 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001427 if (*(args[arg+3])) {
1428 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001429 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001430 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434 }
1435
William Lallemand0f99e342011-10-12 17:50:54 +02001436 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001437 if (*(args[arg+4])) {
1438 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001439 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001440 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001441 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001442 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001443 }
1444 }
1445
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001446 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001447 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001448 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001449 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001450 free(logsrv);
1451 goto out;
1452 }
1453 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001454
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001455 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001456 if (port1 != port2) {
1457 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1458 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001459 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001460 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001461 goto out;
1462 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001463
William Lallemand0f99e342011-10-12 17:50:54 +02001464 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001465 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001466 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468
William Lallemand0f99e342011-10-12 17:50:54 +02001469 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001470 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001471 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1472 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001473
1474 if (global.log_send_hostname != NULL) {
1475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1476 err_code |= ERR_ALERT;
1477 goto out;
1478 }
1479
1480 if (*(args[1]))
1481 name = args[1];
1482 else
1483 name = hostname;
1484
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001485 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001486 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001487 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001488 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1489 if (global.server_state_base != NULL) {
1490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1491 err_code |= ERR_ALERT;
1492 goto out;
1493 }
1494
1495 if (!*(args[1])) {
1496 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1497 err_code |= ERR_FATAL;
1498 goto out;
1499 }
1500
1501 global.server_state_base = strdup(args[1]);
1502 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001503 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1504 if (global.server_state_file != NULL) {
1505 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1506 err_code |= ERR_ALERT;
1507 goto out;
1508 }
1509
1510 if (!*(args[1])) {
1511 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1512 err_code |= ERR_FATAL;
1513 goto out;
1514 }
1515
1516 global.server_state_file = strdup(args[1]);
1517 }
Kevinm48936af2010-12-22 16:08:21 +00001518 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001519 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1520 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001521 if (*(args[1]) == 0) {
1522 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
1525 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001526 chunk_destroy(&global.log_tag);
1527 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001528 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001529 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001530 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1531 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001532 if (global.spread_checks != 0) {
1533 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001534 err_code |= ERR_ALERT;
1535 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001536 }
1537 if (*(args[1]) == 0) {
1538 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001541 }
1542 global.spread_checks = atol(args[1]);
1543 if (global.spread_checks < 0 || global.spread_checks > 50) {
1544 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001548 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1549 const char *err;
1550 unsigned int val;
1551
William Lallemand1a748ae2015-05-19 16:37:23 +02001552 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1553 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001554 if (*(args[1]) == 0) {
1555 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
1558 }
1559
1560 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1561 if (err) {
1562 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1563 err_code |= ERR_ALERT | ERR_FATAL;
1564 }
1565 global.max_spread_checks = val;
1566 if (global.max_spread_checks < 0) {
1567 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1568 err_code |= ERR_ALERT | ERR_FATAL;
1569 }
1570 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001571 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1572#ifdef USE_CPU_AFFINITY
1573 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001574 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001575 unsigned long cpus = 0;
1576
1577 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001578 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001579 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001580 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001581 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001582 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001583 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001584 proc = atol(args[1]);
1585 if (proc >= 1 && proc <= LONGBITS)
1586 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001587 }
1588
1589 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001590 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1591 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001592 err_code |= ERR_ALERT | ERR_FATAL;
1593 goto out;
1594 }
1595
1596 cur_arg = 2;
1597 while (*args[cur_arg]) {
1598 unsigned int low, high;
1599
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001600 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001601 char *dash = strchr(args[cur_arg], '-');
1602
1603 low = high = str2uic(args[cur_arg]);
1604 if (dash)
1605 high = str2uic(dash + 1);
1606
1607 if (high < low) {
1608 unsigned int swap = low;
1609 low = high;
1610 high = swap;
1611 }
1612
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001614 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
1618 }
1619
1620 while (low <= high)
1621 cpus |= 1UL << low++;
1622 }
1623 else {
1624 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1625 file, linenum, args[0], args[cur_arg]);
1626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
1629 cur_arg++;
1630 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001631 for (i = 0; i < LONGBITS; i++)
1632 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001633 global.cpu_map[i] = cpus;
1634#else
1635 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
1638#endif
1639 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001640 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1641 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1642 goto out;
1643
1644 if (*(args[2]) == 0) {
1645 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1646 err_code |= ERR_ALERT | ERR_FATAL;
1647 goto out;
1648 }
1649
1650 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1651 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1652 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
1656 }
1657 else if (!strcmp(args[0], "unsetenv")) {
1658 int arg;
1659
1660 if (*(args[1]) == 0) {
1661 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
1664 }
1665
1666 for (arg = 1; *args[arg]; arg++) {
1667 if (unsetenv(args[arg]) != 0) {
1668 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1669 err_code |= ERR_ALERT | ERR_FATAL;
1670 goto out;
1671 }
1672 }
1673 }
1674 else if (!strcmp(args[0], "resetenv")) {
1675 extern char **environ;
1676 char **env = environ;
1677
1678 /* args contain variable names to keep, one per argument */
1679 while (*env) {
1680 int arg;
1681
1682 /* look for current variable in among all those we want to keep */
1683 for (arg = 1; *args[arg]; arg++) {
1684 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1685 (*env)[strlen(args[arg])] == '=')
1686 break;
1687 }
1688
1689 /* delete this variable */
1690 if (!*args[arg]) {
1691 char *delim = strchr(*env, '=');
1692
1693 if (!delim || delim - *env >= trash.size) {
1694 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
1698
1699 memcpy(trash.str, *env, delim - *env);
1700 trash.str[delim - *env] = 0;
1701
1702 if (unsetenv(trash.str) != 0) {
1703 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707 }
1708 else
1709 env++;
1710 }
1711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001713 struct cfg_kw_list *kwl;
1714 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001715 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001716
1717 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1718 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1719 if (kwl->kw[index].section != CFG_GLOBAL)
1720 continue;
1721 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001722 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001723 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001724 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001726 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001727 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001728 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001729 err_code |= ERR_WARN;
1730 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001731 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001732 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001733 }
1734 }
1735 }
1736
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001740
Willy Tarreau058e9072009-07-20 09:30:05 +02001741 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001742 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001743 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744}
1745
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001746void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001748 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749 defproxy.mode = PR_MODE_TCP;
1750 defproxy.state = PR_STNEW;
1751 defproxy.maxconn = cfg_maxpconn;
1752 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001753 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001754 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001755
Simon Horman66183002013-02-23 10:16:43 +09001756 defproxy.defsrv.check.inter = DEF_CHKINTR;
1757 defproxy.defsrv.check.fastinter = 0;
1758 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001759 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1760 defproxy.defsrv.agent.fastinter = 0;
1761 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001762 defproxy.defsrv.check.rise = DEF_RISETIME;
1763 defproxy.defsrv.check.fall = DEF_FALLTIME;
1764 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1765 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001766 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001767 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001768 defproxy.defsrv.maxqueue = 0;
1769 defproxy.defsrv.minconn = 0;
1770 defproxy.defsrv.maxconn = 0;
1771 defproxy.defsrv.slowstart = 0;
1772 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1773 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1774 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001775
1776 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001777 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778}
1779
Willy Tarreauade5ec42010-01-28 19:33:49 +01001780
Willy Tarreau63af98d2014-05-18 08:11:41 +02001781/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1782 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1783 * ERR_FATAL in case of error.
1784 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001785static int create_cond_regex_rule(const char *file, int line,
1786 struct proxy *px, int dir, int action, int flags,
1787 const char *cmd, const char *reg, const char *repl,
1788 const char **cond_start)
1789{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001790 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001791 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001792 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001793 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001794 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001795 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001796 int cs;
1797 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001798
1799 if (px == &defproxy) {
1800 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001801 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001802 goto err;
1803 }
1804
1805 if (*reg == 0) {
1806 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001807 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001808 goto err;
1809 }
1810
Christopher Faulet898566e2016-10-26 11:06:28 +02001811 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001813
Willy Tarreau5321c422010-01-28 20:35:13 +01001814 if (cond_start &&
1815 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001816 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1817 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1818 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001819 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001820 goto err;
1821 }
1822 }
1823 else if (cond_start && **cond_start) {
1824 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1825 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001826 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001827 goto err;
1828 }
1829
Willy Tarreau63af98d2014-05-18 08:11:41 +02001830 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001831 (dir == SMP_OPT_DIR_REQ) ?
1832 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1833 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1834 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001835
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001836 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001837 if (!preg) {
1838 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001839 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001840 goto err;
1841 }
1842
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001843 cs = !(flags & REG_ICASE);
1844 cap = !(flags & REG_NOSUB);
1845 error = NULL;
1846 if (!regex_comp(reg, preg, cs, cap, &error)) {
1847 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1848 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001849 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001850 goto err;
1851 }
1852
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001853 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001854 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001855 if (repl && err) {
1856 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1857 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001858 ret_code |= ERR_ALERT | ERR_FATAL;
1859 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001860 }
1861
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001862 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code |= ERR_WARN;
1864
1865 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001866
Willy Tarreau63af98d2014-05-18 08:11:41 +02001867 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001868 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001869 err:
1870 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001871 free(errmsg);
1872 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001873}
1874
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875/*
William Lallemand51097192015-04-14 16:35:22 +02001876 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001877 * Returns the error code, 0 if OK, or any combination of :
1878 * - ERR_ABORT: must abort ASAP
1879 * - ERR_FATAL: we can continue parsing but not start the service
1880 * - ERR_WARN: a warning has been emitted
1881 * - ERR_ALERT: an alert has been emitted
1882 * Only the two first ones can stop processing, the two others are just
1883 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001885int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1886{
1887 static struct peers *curpeers = NULL;
1888 struct peer *newpeer = NULL;
1889 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001890 struct bind_conf *bind_conf;
1891 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001892 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001893 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001894
1895 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001896 if (!*args[1]) {
1897 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001898 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001899 goto out;
1900 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001901
William Lallemand6e62fb62015-04-28 16:55:23 +02001902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1903 goto out;
1904
Emeric Brun32da3c42010-09-23 18:39:19 +02001905 err = invalid_char(args[1]);
1906 if (err) {
1907 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1908 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001909 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001910 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 }
1912
1913 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1914 /*
1915 * If there are two proxies with the same name only following
1916 * combinations are allowed:
1917 */
1918 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001919 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001920 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 }
1923 }
1924
Vincent Bernat02779b62016-04-03 13:48:43 +02001925 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001926 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1927 err_code |= ERR_ALERT | ERR_ABORT;
1928 goto out;
1929 }
1930
1931 curpeers->next = peers;
1932 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001933 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001934 curpeers->conf.line = linenum;
1935 curpeers->last_change = now.tv_sec;
1936 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001937 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 }
1939 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001940 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001941 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001942 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001943
1944 if (!*args[2]) {
1945 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1946 file, linenum, args[0]);
1947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
1949 }
1950
1951 err = invalid_char(args[1]);
1952 if (err) {
1953 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1954 file, linenum, *err, args[1]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
Vincent Bernat02779b62016-04-03 13:48:43 +02001959 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001960 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1961 err_code |= ERR_ALERT | ERR_ABORT;
1962 goto out;
1963 }
1964
1965 /* the peers are linked backwards first */
1966 curpeers->count++;
1967 newpeer->next = curpeers->remote;
1968 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001969 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001970 newpeer->conf.line = linenum;
1971
1972 newpeer->last_change = now.tv_sec;
1973 newpeer->id = strdup(args[1]);
1974
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001975 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001976 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001977 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001980 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001981
1982 proto = protocol_by_family(sk->ss_family);
1983 if (!proto || !proto->connect) {
1984 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1985 file, linenum, args[0], args[1]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001989
1990 if (port1 != port2) {
1991 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1992 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
1995 }
1996
Willy Tarreau2aa38802013-02-20 19:20:59 +01001997 if (!port1) {
1998 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1999 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
2002 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002003
Emeric Brun32da3c42010-09-23 18:39:19 +02002004 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002005 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002006 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002007 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 if (strcmp(newpeer->id, localpeer) == 0) {
2010 /* Current is local peer, it define a frontend */
2011 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002012 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002013
2014 if (!curpeers->peers_fe) {
2015 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2017 err_code |= ERR_ALERT | ERR_ABORT;
2018 goto out;
2019 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002020
Willy Tarreau237250c2011-07-29 01:49:03 +02002021 init_new_proxy(curpeers->peers_fe);
2022 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002023 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002024 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2025 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002026 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002027
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002028 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002029
Willy Tarreau902636f2013-03-10 19:44:48 +01002030 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2031 if (errmsg && *errmsg) {
2032 indent_msg(&errmsg, 2);
2033 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002034 }
2035 else
2036 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2037 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 err_code |= ERR_FATAL;
2039 goto out;
2040 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002041
2042 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002043 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002044 l->maxconn = curpeers->peers_fe->maxconn;
2045 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002046 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002047 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002048 l->analysers |= curpeers->peers_fe->fe_req_ana;
2049 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002050 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2051 global.maxsock += l->maxconn;
2052 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002053 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002054 else {
2055 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2056 file, linenum, args[0], args[1],
2057 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2058 err_code |= ERR_FATAL;
2059 goto out;
2060 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002061 }
2062 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002063 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2064 curpeers->state = PR_STSTOPPED;
2065 }
2066 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2067 curpeers->state = PR_STNEW;
2068 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 else if (*args[0] != 0) {
2070 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002076 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002077 return err_code;
2078}
2079
Baptiste Assmann325137d2015-04-13 23:40:55 +02002080/*
2081 * Parse a <resolvers> section.
2082 * Returns the error code, 0 if OK, or any combination of :
2083 * - ERR_ABORT: must abort ASAP
2084 * - ERR_FATAL: we can continue parsing but not start the service
2085 * - ERR_WARN: a warning has been emitted
2086 * - ERR_ALERT: an alert has been emitted
2087 * Only the two first ones can stop processing, the two others are just
2088 * indicators.
2089 */
2090int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2091{
2092 static struct dns_resolvers *curr_resolvers = NULL;
2093 struct dns_nameserver *newnameserver = NULL;
2094 const char *err;
2095 int err_code = 0;
2096 char *errmsg = NULL;
2097
2098 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2099 if (!*args[1]) {
2100 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2101 err_code |= ERR_ALERT | ERR_ABORT;
2102 goto out;
2103 }
2104
2105 err = invalid_char(args[1]);
2106 if (err) {
2107 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2108 file, linenum, *err, args[0], args[1]);
2109 err_code |= ERR_ALERT | ERR_ABORT;
2110 goto out;
2111 }
2112
2113 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2114 /* Error if two resolvers owns the same name */
2115 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2116 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2117 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2118 err_code |= ERR_ALERT | ERR_ABORT;
2119 }
2120 }
2121
Vincent Bernat02779b62016-04-03 13:48:43 +02002122 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2124 err_code |= ERR_ALERT | ERR_ABORT;
2125 goto out;
2126 }
2127
2128 /* default values */
2129 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2130 curr_resolvers->conf.file = strdup(file);
2131 curr_resolvers->conf.line = linenum;
2132 curr_resolvers->id = strdup(args[1]);
2133 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002134 /* default hold period for nx, other, refuse and timeout is 30s */
2135 curr_resolvers->hold.nx = 30000;
2136 curr_resolvers->hold.other = 30000;
2137 curr_resolvers->hold.refused = 30000;
2138 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002139 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002140 curr_resolvers->hold.valid = 10000;
2141 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002142 curr_resolvers->resolve_retries = 3;
2143 LIST_INIT(&curr_resolvers->nameserver_list);
2144 LIST_INIT(&curr_resolvers->curr_resolution);
2145 }
2146 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2147 struct sockaddr_storage *sk;
2148 int port1, port2;
2149 struct protocol *proto;
2150
2151 if (!*args[2]) {
2152 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2153 file, linenum, args[0]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
2157
2158 err = invalid_char(args[1]);
2159 if (err) {
2160 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2161 file, linenum, *err, args[1]);
2162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
2164 }
2165
Baptiste Assmanna315c552015-11-02 22:55:49 +01002166 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2167 /* Error if two resolvers owns the same name */
2168 if (strcmp(newnameserver->id, args[1]) == 0) {
2169 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2170 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2171 err_code |= ERR_ALERT | ERR_FATAL;
2172 }
2173 }
2174
Vincent Bernat02779b62016-04-03 13:48:43 +02002175 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2177 err_code |= ERR_ALERT | ERR_ABORT;
2178 goto out;
2179 }
2180
2181 /* the nameservers are linked backward first */
2182 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2183 curr_resolvers->count_nameservers++;
2184 newnameserver->resolvers = curr_resolvers;
2185 newnameserver->conf.file = strdup(file);
2186 newnameserver->conf.line = linenum;
2187 newnameserver->id = strdup(args[1]);
2188
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002189 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002190 if (!sk) {
2191 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
2196 proto = protocol_by_family(sk->ss_family);
2197 if (!proto || !proto->connect) {
2198 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2199 file, linenum, args[0], args[1]);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
2204 if (port1 != port2) {
2205 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2206 file, linenum, args[0], args[1], args[2]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002211 if (!port1 && !port2) {
2212 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2213 file, linenum, args[0], args[1]);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
2216 }
2217
Baptiste Assmann325137d2015-04-13 23:40:55 +02002218 newnameserver->addr = *sk;
2219 }
2220 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2221 const char *res;
2222 unsigned int time;
2223
2224 if (!*args[2]) {
2225 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2226 file, linenum, args[0]);
2227 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2232 if (res) {
2233 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2234 file, linenum, *res, args[0]);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002238 if (strcmp(args[1], "nx") == 0)
2239 curr_resolvers->hold.nx = time;
2240 else if (strcmp(args[1], "other") == 0)
2241 curr_resolvers->hold.other = time;
2242 else if (strcmp(args[1], "refused") == 0)
2243 curr_resolvers->hold.refused = time;
2244 else if (strcmp(args[1], "timeout") == 0)
2245 curr_resolvers->hold.timeout = time;
2246 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002247 curr_resolvers->hold.valid = time;
2248 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002249 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2250 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254
2255 }
2256 else if (strcmp(args[0], "resolve_retries") == 0) {
2257 if (!*args[1]) {
2258 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2259 file, linenum, args[0]);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263 curr_resolvers->resolve_retries = atoi(args[1]);
2264 }
2265 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002266 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002267 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2268 file, linenum, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002272 else if (strcmp(args[1], "retry") == 0) {
2273 const char *res;
2274 unsigned int timeout_retry;
2275
2276 if (!*args[2]) {
2277 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2278 file, linenum, args[0], args[1]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2283 if (res) {
2284 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2285 file, linenum, *res, args[0], args[1]);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289 curr_resolvers->timeout.retry = timeout_retry;
2290 }
2291 else {
2292 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2293 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002297 } /* neither "nameserver" nor "resolvers" */
2298 else if (*args[0] != 0) {
2299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
2303
2304 out:
2305 free(errmsg);
2306 return err_code;
2307}
Simon Horman0d16a402015-01-30 11:22:58 +09002308
2309/*
William Lallemand51097192015-04-14 16:35:22 +02002310 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002311 * Returns the error code, 0 if OK, or any combination of :
2312 * - ERR_ABORT: must abort ASAP
2313 * - ERR_FATAL: we can continue parsing but not start the service
2314 * - ERR_WARN: a warning has been emitted
2315 * - ERR_ALERT: an alert has been emitted
2316 * Only the two first ones can stop processing, the two others are just
2317 * indicators.
2318 */
2319int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2320{
2321 static struct mailers *curmailers = NULL;
2322 struct mailer *newmailer = NULL;
2323 const char *err;
2324 int err_code = 0;
2325 char *errmsg = NULL;
2326
2327 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2328 if (!*args[1]) {
2329 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2330 err_code |= ERR_ALERT | ERR_ABORT;
2331 goto out;
2332 }
2333
2334 err = invalid_char(args[1]);
2335 if (err) {
2336 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2337 file, linenum, *err, args[0], args[1]);
2338 err_code |= ERR_ALERT | ERR_ABORT;
2339 goto out;
2340 }
2341
2342 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2343 /*
2344 * If there are two proxies with the same name only following
2345 * combinations are allowed:
2346 */
2347 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002348 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002349 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002351 }
2352 }
2353
Vincent Bernat02779b62016-04-03 13:48:43 +02002354 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2356 err_code |= ERR_ALERT | ERR_ABORT;
2357 goto out;
2358 }
2359
2360 curmailers->next = mailers;
2361 mailers = curmailers;
2362 curmailers->conf.file = strdup(file);
2363 curmailers->conf.line = linenum;
2364 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002365 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2366 * But need enough time so that timeouts don't occur
2367 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002368 }
2369 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2370 struct sockaddr_storage *sk;
2371 int port1, port2;
2372 struct protocol *proto;
2373
2374 if (!*args[2]) {
2375 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2376 file, linenum, args[0]);
2377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
2379 }
2380
2381 err = invalid_char(args[1]);
2382 if (err) {
2383 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2384 file, linenum, *err, args[1]);
2385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
2387 }
2388
Vincent Bernat02779b62016-04-03 13:48:43 +02002389 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
2393 }
2394
2395 /* the mailers are linked backwards first */
2396 curmailers->count++;
2397 newmailer->next = curmailers->mailer_list;
2398 curmailers->mailer_list = newmailer;
2399 newmailer->mailers = curmailers;
2400 newmailer->conf.file = strdup(file);
2401 newmailer->conf.line = linenum;
2402
2403 newmailer->id = strdup(args[1]);
2404
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002405 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002406 if (!sk) {
2407 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
2412 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002413 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2414 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002415 file, linenum, args[0], args[1]);
2416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
2418 }
2419
2420 if (port1 != port2) {
2421 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2422 file, linenum, args[0], args[1], args[2]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 if (!port1) {
2428 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2429 file, linenum, args[0], args[1], args[2]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433
2434 newmailer->addr = *sk;
2435 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002436 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002437 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002438 }
2439 else if (strcmp(args[0], "timeout") == 0) {
2440 if (!*args[1]) {
2441 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2442 file, linenum, args[0]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446 else if (strcmp(args[1], "mail") == 0) {
2447 const char *res;
2448 unsigned int timeout_mail;
2449 if (!*args[2]) {
2450 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2451 file, linenum, args[0], args[1]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2456 if (res) {
2457 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2458 file, linenum, *res, args[0]);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462 if (timeout_mail <= 0) {
2463 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467 curmailers->timeout.mail = timeout_mail;
2468 } else {
2469 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2470 file, linenum, args[0], args[1]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
2474 }
Simon Horman0d16a402015-01-30 11:22:58 +09002475 else if (*args[0] != 0) {
2476 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481out:
2482 free(errmsg);
2483 return err_code;
2484}
2485
Simon Horman9dc49962015-01-30 11:22:59 +09002486static void free_email_alert(struct proxy *p)
2487{
2488 free(p->email_alert.mailers.name);
2489 p->email_alert.mailers.name = NULL;
2490 free(p->email_alert.from);
2491 p->email_alert.from = NULL;
2492 free(p->email_alert.to);
2493 p->email_alert.to = NULL;
2494 free(p->email_alert.myhostname);
2495 p->email_alert.myhostname = NULL;
2496}
2497
Willy Tarreau3842f002009-06-14 11:39:52 +02002498int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499{
2500 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002501 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002502 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002503 int rc;
2504 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002505 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002506 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002507 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002508 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002509 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510
Willy Tarreau977b8e42006-12-29 14:19:17 +01002511 if (!strcmp(args[0], "listen"))
2512 rc = PR_CAP_LISTEN;
2513 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002514 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002515 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002516 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002517 else
2518 rc = PR_CAP_NONE;
2519
2520 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 if (!*args[1]) {
2522 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002523 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_ABORT;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002528
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002529 err = invalid_char(args[1]);
2530 if (err) {
2531 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2532 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002534 }
2535
Willy Tarreau8f50b682015-05-26 11:45:02 +02002536 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2537 if (curproxy) {
2538 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2539 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2540 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002542 }
2543
Vincent Bernat02779b62016-04-03 13:48:43 +02002544 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_ABORT;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002549
Willy Tarreau97cb7802010-01-03 20:23:58 +01002550 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 curproxy->next = proxy;
2552 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002553 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2554 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002555 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002558 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559
William Lallemand6e62fb62015-04-28 16:55:23 +02002560 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2561 if (curproxy->cap & PR_CAP_FE)
2562 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565
2566 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002567 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002568 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002572 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002573 curproxy->no_options = defproxy.no_options;
2574 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002575 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002576 curproxy->except_net = defproxy.except_net;
2577 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002578 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002579 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002581 if (defproxy.fwdfor_hdr_len) {
2582 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2583 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2584 }
2585
Willy Tarreaub86db342009-11-30 11:50:16 +01002586 if (defproxy.orgto_hdr_len) {
2587 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2588 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2589 }
2590
Mark Lamourinec2247f02012-01-04 13:02:01 -05002591 if (defproxy.server_id_hdr_len) {
2592 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2593 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2594 }
2595
Willy Tarreau977b8e42006-12-29 14:19:17 +01002596 if (curproxy->cap & PR_CAP_FE) {
2597 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002598 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002599 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600
2601 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002602 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2603 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604
2605 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002609 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002610 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611 curproxy->fullconn = defproxy.fullconn;
2612 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002613 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002614 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002616 if (defproxy.check_req) {
2617 curproxy->check_req = calloc(1, defproxy.check_len);
2618 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2619 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002622 if (defproxy.expect_str) {
2623 curproxy->expect_str = strdup(defproxy.expect_str);
2624 if (defproxy.expect_regex) {
2625 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002626 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2627 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002628 }
2629 }
2630
Willy Tarreau67402132012-05-31 20:40:20 +02002631 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002632 if (defproxy.cookie_name)
2633 curproxy->cookie_name = strdup(defproxy.cookie_name);
2634 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002635 if (defproxy.cookie_domain)
2636 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002637
Willy Tarreau31936852010-10-06 16:59:56 +02002638 if (defproxy.cookie_maxidle)
2639 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2640
2641 if (defproxy.cookie_maxlife)
2642 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2643
Emeric Brun647caf12009-06-30 17:57:00 +02002644 if (defproxy.rdp_cookie_name)
2645 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2646 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2647
Willy Tarreau01732802007-11-01 22:48:15 +01002648 if (defproxy.url_param_name)
2649 curproxy->url_param_name = strdup(defproxy.url_param_name);
2650 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002651
Benoitaffb4812009-03-25 13:02:10 +01002652 if (defproxy.hh_name)
2653 curproxy->hh_name = strdup(defproxy.hh_name);
2654 curproxy->hh_len = defproxy.hh_len;
2655 curproxy->hh_match_domain = defproxy.hh_match_domain;
2656
Willy Tarreauef9a3602012-12-08 22:29:20 +01002657 if (defproxy.conn_src.iface_name)
2658 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2659 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002660 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002661#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002662 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002663#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002664 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002667 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002668 if (defproxy.capture_name)
2669 curproxy->capture_name = strdup(defproxy.capture_name);
2670 curproxy->capture_namelen = defproxy.capture_namelen;
2671 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673
Willy Tarreau977b8e42006-12-29 14:19:17 +01002674 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002675 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002676 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002677 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002678 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002679 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002680 curproxy->mon_net = defproxy.mon_net;
2681 curproxy->mon_mask = defproxy.mon_mask;
2682 if (defproxy.monitor_uri)
2683 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2684 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002685 if (defproxy.defbe.name)
2686 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002687
2688 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002689 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2690 if (curproxy->conf.logformat_string &&
2691 curproxy->conf.logformat_string != default_http_log_format &&
2692 curproxy->conf.logformat_string != default_tcp_log_format &&
2693 curproxy->conf.logformat_string != clf_http_log_format)
2694 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2695
2696 if (defproxy.conf.lfs_file) {
2697 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2698 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2699 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002700
2701 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2702 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2703 if (curproxy->conf.logformat_sd_string &&
2704 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2705 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2706
2707 if (defproxy.conf.lfsd_file) {
2708 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2709 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2710 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002711 }
2712
2713 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002714 curproxy->timeout.connect = defproxy.timeout.connect;
2715 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002716 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002717 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002718 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002719 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002720 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002721 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002722 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002723 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002724 }
2725
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002727 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002728
2729 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002730 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002731 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002732 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002733 LIST_INIT(&node->list);
2734 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2735 }
2736
Willy Tarreau62a61232013-04-12 18:13:46 +02002737 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2738 if (curproxy->conf.uniqueid_format_string)
2739 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2740
Dragan Dosen43885c72015-10-01 13:18:13 +02002741 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002742
Willy Tarreau62a61232013-04-12 18:13:46 +02002743 if (defproxy.conf.uif_file) {
2744 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2745 curproxy->conf.uif_line = defproxy.conf.uif_line;
2746 }
William Lallemanda73203e2012-03-12 12:48:57 +01002747
2748 /* copy default header unique id */
2749 if (defproxy.header_unique_id)
2750 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2751
William Lallemand82fe75c2012-10-23 10:25:10 +02002752 /* default compression options */
2753 if (defproxy.comp != NULL) {
2754 curproxy->comp = calloc(1, sizeof(struct comp));
2755 curproxy->comp->algos = defproxy.comp->algos;
2756 curproxy->comp->types = defproxy.comp->types;
2757 }
2758
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002760 curproxy->conf.used_listener_id = EB_ROOT;
2761 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002762
Simon Horman98637e52014-06-20 12:30:16 +09002763 if (defproxy.check_path)
2764 curproxy->check_path = strdup(defproxy.check_path);
2765 if (defproxy.check_command)
2766 curproxy->check_command = strdup(defproxy.check_command);
2767
Simon Horman9dc49962015-01-30 11:22:59 +09002768 if (defproxy.email_alert.mailers.name)
2769 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2770 if (defproxy.email_alert.from)
2771 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2772 if (defproxy.email_alert.to)
2773 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2774 if (defproxy.email_alert.myhostname)
2775 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002776 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002777 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002778
Willy Tarreau93893792009-07-23 13:19:11 +02002779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 }
2781 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2782 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002783 /* FIXME-20070101: we should do this too at the end of the
2784 * config parsing to free all default values.
2785 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002786 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2787 err_code |= ERR_ABORT;
2788 goto out;
2789 }
2790
Willy Tarreaua534fea2008-08-03 12:19:50 +02002791 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002792 free(defproxy.check_command);
2793 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002794 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002795 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002796 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002797 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002798 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002799 free(defproxy.capture_name);
2800 free(defproxy.monitor_uri);
2801 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002802 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002803 free(defproxy.fwdfor_hdr_name);
2804 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002805 free(defproxy.orgto_hdr_name);
2806 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002807 free(defproxy.server_id_hdr_name);
2808 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002809 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002810 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002811 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002812 free(defproxy.expect_regex);
2813 defproxy.expect_regex = NULL;
2814 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002815
Willy Tarreau62a61232013-04-12 18:13:46 +02002816 if (defproxy.conf.logformat_string != default_http_log_format &&
2817 defproxy.conf.logformat_string != default_tcp_log_format &&
2818 defproxy.conf.logformat_string != clf_http_log_format)
2819 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002820
Willy Tarreau62a61232013-04-12 18:13:46 +02002821 free(defproxy.conf.uniqueid_format_string);
2822 free(defproxy.conf.lfs_file);
2823 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002824 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002825 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002826
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002827 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2828 free(defproxy.conf.logformat_sd_string);
2829 free(defproxy.conf.lfsd_file);
2830
Willy Tarreaua534fea2008-08-03 12:19:50 +02002831 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002832 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002833
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 /* we cannot free uri_auth because it might already be used */
2835 init_default_instance();
2836 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002837 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2838 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002839 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
2842 else if (curproxy == NULL) {
2843 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002847
2848 /* update the current file and line being parsed */
2849 curproxy->conf.args.file = curproxy->conf.file;
2850 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851
2852 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002853 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2854 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2855 if (err_code & ERR_FATAL)
2856 goto out;
2857 }
2858 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002859 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002860 int cur_arg;
2861
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 if (curproxy == &defproxy) {
2863 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002867 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869
Willy Tarreau24709282013-03-10 21:32:12 +01002870 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002871 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 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 Tarreaub1e52e82008-01-13 14:49:51 +01002876
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002877 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002878
2879 /* use default settings for unix sockets */
2880 bind_conf->ux.uid = global.unix_bind.ux.uid;
2881 bind_conf->ux.gid = global.unix_bind.ux.gid;
2882 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002883
2884 /* NOTE: the following line might create several listeners if there
2885 * are comma-separated IPs or port ranges. So all further processing
2886 * will have to be applied to all listeners created after last_listen.
2887 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002888 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2889 if (errmsg && *errmsg) {
2890 indent_msg(&errmsg, 2);
2891 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002892 }
2893 else
2894 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2895 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002899
Willy Tarreau4348fad2012-09-20 16:48:07 +02002900 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2901 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002902 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002903 }
2904
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002905 cur_arg = 2;
2906 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002907 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002908 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002909 char *err;
2910
Willy Tarreau26982662012-09-12 23:17:10 +02002911 kw = bind_find_kw(args[cur_arg]);
2912 if (kw) {
2913 char *err = NULL;
2914 int code;
2915
2916 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002917 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2918 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002919 cur_arg += 1 + kw->skip ;
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923
Willy Tarreau4348fad2012-09-20 16:48:07 +02002924 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002925 err_code |= code;
2926
2927 if (code) {
2928 if (err && *err) {
2929 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002930 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002931 }
2932 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002933 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2934 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002935 if (code & ERR_FATAL) {
2936 free(err);
2937 cur_arg += 1 + kw->skip;
2938 goto out;
2939 }
2940 }
2941 free(err);
2942 cur_arg += 1 + kw->skip;
2943 continue;
2944 }
2945
Willy Tarreau8638f482012-09-18 18:01:17 +02002946 err = NULL;
2947 if (!bind_dumped) {
2948 bind_dump_kws(&err);
2949 indent_msg(&err, 4);
2950 bind_dumped = 1;
2951 }
2952
2953 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2954 file, linenum, args[0], args[1], args[cur_arg],
2955 err ? " Registered keywords :" : "", err ? err : "");
2956 free(err);
2957
Willy Tarreau93893792009-07-23 13:19:11 +02002958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002960 }
Willy Tarreau93893792009-07-23 13:19:11 +02002961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 }
2963 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002964 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 /* flush useless bits */
2974 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002977 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002978 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002980
William Lallemanddf1425a2015-04-28 20:17:49 +02002981 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2982 goto out;
2983
Willy Tarreau1c47f852006-07-09 08:22:27 +02002984 if (!*args[1]) {
2985 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2986 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002989 }
2990
Willy Tarreaua534fea2008-08-03 12:19:50 +02002991 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002992 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002993 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002994 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002995 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2996
Willy Tarreau93893792009-07-23 13:19:11 +02002997 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003000 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3001 goto out;
3002
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3004 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3005 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3006 else {
3007 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
3011 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003012 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003013 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003014
3015 if (curproxy == &defproxy) {
3016 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3017 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003020 }
3021
William Lallemanddf1425a2015-04-28 20:17:49 +02003022 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3023 goto out;
3024
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003025 if (!*args[1]) {
3026 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003030 }
3031
3032 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003033 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003034 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003035
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003036 if (curproxy->uuid <= 0) {
3037 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003038 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003041 }
3042
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003043 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3044 if (node) {
3045 struct proxy *target = container_of(node, struct proxy, conf.id);
3046 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3047 file, linenum, proxy_type_str(curproxy), curproxy->id,
3048 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003053 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003054 else if (!strcmp(args[0], "description")) {
3055 int i, len=0;
3056 char *d;
3057
Cyril Bonté99ed3272010-01-24 23:29:44 +01003058 if (curproxy == &defproxy) {
3059 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3060 file, linenum, args[0]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
3063 }
3064
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003065 if (!*args[1]) {
3066 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3067 file, linenum, args[0]);
3068 return -1;
3069 }
3070
Willy Tarreau348acfe2014-04-14 15:00:39 +02003071 for (i = 1; *args[i]; i++)
3072 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003073
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003074 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003075 curproxy->desc = d;
3076
Willy Tarreau348acfe2014-04-14 15:00:39 +02003077 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3078 for (i = 2; *args[i]; i++)
3079 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003080
3081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003083 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 curproxy->state = PR_STSTOPPED;
3086 }
3087 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003088 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 curproxy->state = PR_STNEW;
3091 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003092 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3093 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003094 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003095
3096 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003097 unsigned int low, high;
3098
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003099 if (strcmp(args[cur_arg], "all") == 0) {
3100 set = 0;
3101 break;
3102 }
3103 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003104 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003105 }
3106 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003107 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003108 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003109 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003110 char *dash = strchr(args[cur_arg], '-');
3111
3112 low = high = str2uic(args[cur_arg]);
3113 if (dash)
3114 high = str2uic(dash + 1);
3115
3116 if (high < low) {
3117 unsigned int swap = low;
3118 low = high;
3119 high = swap;
3120 }
3121
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003122 if (low < 1 || high > LONGBITS) {
3123 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3124 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003127 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003128 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003129 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003130 }
3131 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003132 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3133 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003136 }
3137 cur_arg++;
3138 }
3139 curproxy->bind_proc = set;
3140 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003141 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003142 if (curproxy == &defproxy) {
3143 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003146 }
3147
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003148 err = invalid_char(args[1]);
3149 if (err) {
3150 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3151 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003153 }
3154
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003155 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003156 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3157 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003160 }
3161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3163 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164
Willy Tarreau977b8e42006-12-29 14:19:17 +01003165 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003167
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 if (*(args[1]) == 0) {
3169 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3170 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003174
Willy Tarreau67402132012-05-31 20:40:20 +02003175 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003176 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003177 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003178 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 curproxy->cookie_name = strdup(args[1]);
3180 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003181
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 cur_arg = 2;
3183 while (*(args[cur_arg])) {
3184 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003185 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 }
3187 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003188 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 }
3190 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003191 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 }
3193 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003194 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003197 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003199 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003200 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003203 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003205 else if (!strcmp(args[cur_arg], "httponly")) {
3206 curproxy->ck_opts |= PR_CK_HTTPONLY;
3207 }
3208 else if (!strcmp(args[cur_arg], "secure")) {
3209 curproxy->ck_opts |= PR_CK_SECURE;
3210 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003211 else if (!strcmp(args[cur_arg], "domain")) {
3212 if (!*args[cur_arg + 1]) {
3213 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3214 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003217 }
3218
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003219 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003220 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003221 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3222 " dots nor does not start with a dot."
3223 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003224 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003225 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003226 }
3227
3228 err = invalid_domainchar(args[cur_arg + 1]);
3229 if (err) {
3230 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3231 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003234 }
3235
Willy Tarreau68a897b2009-12-03 23:28:34 +01003236 if (!curproxy->cookie_domain) {
3237 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3238 } else {
3239 /* one domain was already specified, add another one by
3240 * building the string which will be returned along with
3241 * the cookie.
3242 */
3243 char *new_ptr;
3244 int new_len = strlen(curproxy->cookie_domain) +
3245 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3246 new_ptr = malloc(new_len);
3247 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3248 free(curproxy->cookie_domain);
3249 curproxy->cookie_domain = new_ptr;
3250 }
Willy Tarreau31936852010-10-06 16:59:56 +02003251 cur_arg++;
3252 }
3253 else if (!strcmp(args[cur_arg], "maxidle")) {
3254 unsigned int maxidle;
3255 const char *res;
3256
3257 if (!*args[cur_arg + 1]) {
3258 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3259 file, linenum, args[cur_arg]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
3262 }
3263
3264 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3265 if (res) {
3266 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3267 file, linenum, *res, args[cur_arg]);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271 curproxy->cookie_maxidle = maxidle;
3272 cur_arg++;
3273 }
3274 else if (!strcmp(args[cur_arg], "maxlife")) {
3275 unsigned int maxlife;
3276 const char *res;
3277
3278 if (!*args[cur_arg + 1]) {
3279 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3280 file, linenum, args[cur_arg]);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283 }
3284
3285 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3286 if (res) {
3287 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3288 file, linenum, *res, args[cur_arg]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
3291 }
3292 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003293 cur_arg++;
3294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003296 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301 cur_arg++;
3302 }
Willy Tarreau67402132012-05-31 20:40:20 +02003303 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3305 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
3308
Willy Tarreau67402132012-05-31 20:40:20 +02003309 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3311 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003314
Willy Tarreau67402132012-05-31 20:40:20 +02003315 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003316 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3317 file, linenum);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003321 else if (!strcmp(args[0], "email-alert")) {
3322 if (*(args[1]) == 0) {
3323 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3324 file, linenum, args[0]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
3329 if (!strcmp(args[1], "from")) {
3330 if (*(args[1]) == 0) {
3331 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3332 file, linenum, args[1]);
3333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
3335 }
3336 free(curproxy->email_alert.from);
3337 curproxy->email_alert.from = strdup(args[2]);
3338 }
3339 else if (!strcmp(args[1], "mailers")) {
3340 if (*(args[1]) == 0) {
3341 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3342 file, linenum, args[1]);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
3346 free(curproxy->email_alert.mailers.name);
3347 curproxy->email_alert.mailers.name = strdup(args[2]);
3348 }
3349 else if (!strcmp(args[1], "myhostname")) {
3350 if (*(args[1]) == 0) {
3351 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3352 file, linenum, args[1]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356 free(curproxy->email_alert.myhostname);
3357 curproxy->email_alert.myhostname = strdup(args[2]);
3358 }
Simon Horman64e34162015-02-06 11:11:57 +09003359 else if (!strcmp(args[1], "level")) {
3360 curproxy->email_alert.level = get_log_level(args[2]);
3361 if (curproxy->email_alert.level < 0) {
3362 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3363 file, linenum, args[1], args[2]);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
3367 }
Simon Horman9dc49962015-01-30 11:22:59 +09003368 else if (!strcmp(args[1], "to")) {
3369 if (*(args[1]) == 0) {
3370 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3371 file, linenum, args[1]);
3372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
3374 }
3375 free(curproxy->email_alert.to);
3376 curproxy->email_alert.to = strdup(args[2]);
3377 }
3378 else {
3379 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3380 file, linenum, args[1]);
3381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
3383 }
Simon Horman64e34162015-02-06 11:11:57 +09003384 /* Indicate that the email_alert is at least partially configured */
3385 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003386 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003387 else if (!strcmp(args[0], "external-check")) {
3388 if (*(args[1]) == 0) {
3389 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3390 file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
3395 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003396 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003397 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003398 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003399 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3400 file, linenum, args[1]);
3401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
3403 }
3404 free(curproxy->check_command);
3405 curproxy->check_command = strdup(args[2]);
3406 }
3407 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003408 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003409 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003410 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003411 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3412 file, linenum, args[1]);
3413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
3415 }
3416 free(curproxy->check_path);
3417 curproxy->check_path = strdup(args[2]);
3418 }
3419 else {
3420 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3421 file, linenum, args[1]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003426 else if (!strcmp(args[0], "persist")) { /* persist */
3427 if (*(args[1]) == 0) {
3428 Alert("parsing [%s:%d] : missing persist method.\n",
3429 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003432 }
3433
3434 if (!strncmp(args[1], "rdp-cookie", 10)) {
3435 curproxy->options2 |= PR_O2_RDPC_PRST;
3436
Emeric Brunb982a3d2010-01-04 15:45:53 +01003437 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003438 const char *beg, *end;
3439
3440 beg = args[1] + 11;
3441 end = strchr(beg, ')');
3442
William Lallemanddf1425a2015-04-28 20:17:49 +02003443 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3444 goto out;
3445
Emeric Brun647caf12009-06-30 17:57:00 +02003446 if (!end || end == beg) {
3447 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3448 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003451 }
3452
3453 free(curproxy->rdp_cookie_name);
3454 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3455 curproxy->rdp_cookie_len = end-beg;
3456 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003457 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003458 free(curproxy->rdp_cookie_name);
3459 curproxy->rdp_cookie_name = strdup("msts");
3460 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3461 }
3462 else { /* syntax */
3463 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3464 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003467 }
3468 }
3469 else {
3470 Alert("parsing [%s:%d] : unknown persist method.\n",
3471 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003474 }
3475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003477 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003481 else if (!strcmp(args[0], "load-server-state-from-file")) {
3482 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3483 err_code |= ERR_WARN;
3484 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3485 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3486 }
3487 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3488 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3489 }
3490 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3491 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3492 }
3493 else {
3494 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3495 file, linenum, args[0], args[1]);
3496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
3498 }
3499 }
3500 else if (!strcmp(args[0], "server-state-file-name")) {
3501 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3502 err_code |= ERR_WARN;
3503 if (*(args[1]) == 0) {
3504 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3505 file, linenum, args[0]);
3506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
3508 }
3509 else if (!strcmp(args[1], "use-backend-name"))
3510 curproxy->server_state_file_name = strdup(curproxy->id);
3511 else
3512 curproxy->server_state_file_name = strdup(args[1]);
3513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003515 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003517
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003519 if (curproxy == &defproxy) {
3520 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524
William Lallemand1a748ae2015-05-19 16:37:23 +02003525 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3526 goto out;
3527
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 if (*(args[4]) == 0) {
3529 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003534 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 curproxy->capture_name = strdup(args[2]);
3536 curproxy->capture_namelen = strlen(curproxy->capture_name);
3537 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 curproxy->to_log |= LW_COOKIE;
3539 }
3540 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3541 struct cap_hdr *hdr;
3542
3543 if (curproxy == &defproxy) {
3544 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 +02003545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003547 }
3548
William Lallemand1a748ae2015-05-19 16:37:23 +02003549 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3550 goto out;
3551
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3553 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3554 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 }
3558
Vincent Bernat02779b62016-04-03 13:48:43 +02003559 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 hdr->next = curproxy->req_cap;
3561 hdr->name = strdup(args[3]);
3562 hdr->namelen = strlen(args[3]);
3563 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003564 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 hdr->index = curproxy->nb_req_cap++;
3566 curproxy->req_cap = hdr;
3567 curproxy->to_log |= LW_REQHDR;
3568 }
3569 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3570 struct cap_hdr *hdr;
3571
3572 if (curproxy == &defproxy) {
3573 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 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 }
3577
William Lallemand1a748ae2015-05-19 16:37:23 +02003578 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3579 goto out;
3580
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3582 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3583 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003587 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 hdr->next = curproxy->rsp_cap;
3589 hdr->name = strdup(args[3]);
3590 hdr->namelen = strlen(args[3]);
3591 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003592 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 hdr->index = curproxy->nb_rsp_cap++;
3594 curproxy->rsp_cap = hdr;
3595 curproxy->to_log |= LW_RSPHDR;
3596 }
3597 else {
3598 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3599 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 }
3603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003605 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003607
William Lallemanddf1425a2015-04-28 20:17:49 +02003608 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3609 goto out;
3610
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 if (*(args[1]) == 0) {
3612 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3613 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 }
3617 curproxy->conn_retries = atol(args[1]);
3618 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003619 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003620 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003621
3622 if (curproxy == &defproxy) {
3623 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
3626 }
3627
Willy Tarreau20b0de52012-12-24 15:45:22 +01003628 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003629 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003630 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3631 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3632 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3633 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003634 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 +01003635 file, linenum, args[0]);
3636 err_code |= ERR_WARN;
3637 }
3638
Willy Tarreauff011f22011-01-06 17:51:27 +01003639 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003640
Willy Tarreauff011f22011-01-06 17:51:27 +01003641 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003642 err_code |= ERR_ALERT | ERR_ABORT;
3643 goto out;
3644 }
3645
Willy Tarreau5002f572014-04-23 01:32:02 +02003646 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003647 err_code |= warnif_cond_conflicts(rule->cond,
3648 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3649 file, linenum);
3650
Willy Tarreauff011f22011-01-06 17:51:27 +01003651 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003652 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003653 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003654 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003655
3656 if (curproxy == &defproxy) {
3657 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
3660 }
3661
3662 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003663 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003664 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3665 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003666 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3667 file, linenum, args[0]);
3668 err_code |= ERR_WARN;
3669 }
3670
3671 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3672
3673 if (!rule) {
3674 err_code |= ERR_ALERT | ERR_ABORT;
3675 goto out;
3676 }
3677
3678 err_code |= warnif_cond_conflicts(rule->cond,
3679 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3680 file, linenum);
3681
3682 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3683 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003684 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3685 /* set the header name and length into the proxy structure */
3686 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3687 err_code |= ERR_WARN;
3688
3689 if (!*args[1]) {
3690 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3691 file, linenum, args[0]);
3692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
3694 }
3695
3696 /* set the desired header name */
3697 free(curproxy->server_id_hdr_name);
3698 curproxy->server_id_hdr_name = strdup(args[1]);
3699 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3700 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003701 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003702 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003703
Willy Tarreaub099aca2008-10-12 17:26:37 +02003704 if (curproxy == &defproxy) {
3705 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003708 }
3709
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003710 /* emulate "block" using "http-request block". Since these rules are supposed to
3711 * be processed before all http-request rules, we put them into their own list
3712 * and will insert them at the end.
3713 */
3714 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3715 if (!rule) {
3716 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003717 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003718 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003719 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3720 err_code |= warnif_cond_conflicts(rule->cond,
3721 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3722 file, linenum);
3723 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003724
3725 if (!already_warned(WARN_BLOCK_DEPRECATED))
3726 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]);
3727
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003728 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003729 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003730 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003731
Cyril Bonté99ed3272010-01-24 23:29:44 +01003732 if (curproxy == &defproxy) {
3733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
3736 }
3737
Willy Tarreaube4653b2015-05-28 15:26:58 +02003738 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003739 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3740 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003743 }
3744
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003745 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003746 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003747 err_code |= warnif_cond_conflicts(rule->cond,
3748 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3749 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003750 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003751 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003752 struct switching_rule *rule;
3753
Willy Tarreaub099aca2008-10-12 17:26:37 +02003754 if (curproxy == &defproxy) {
3755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003758 }
3759
Willy Tarreau55ea7572007-06-17 19:56:27 +02003760 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003762
3763 if (*(args[1]) == 0) {
3764 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003767 }
3768
Willy Tarreauf51658d2014-04-23 01:21:56 +02003769 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3770 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3771 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3772 file, linenum, errmsg);
3773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
3775 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003776
Willy Tarreauf51658d2014-04-23 01:21:56 +02003777 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003778 }
3779
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003780 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003781 if (!rule) {
3782 Alert("Out of memory error.\n");
3783 goto out;
3784 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003785 rule->cond = cond;
3786 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003787 rule->line = linenum;
3788 rule->file = strdup(file);
3789 if (!rule->file) {
3790 Alert("Out of memory error.\n");
3791 goto out;
3792 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003793 LIST_INIT(&rule->list);
3794 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3795 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003796 else if (strcmp(args[0], "use-server") == 0) {
3797 struct server_rule *rule;
3798
3799 if (curproxy == &defproxy) {
3800 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
3804
3805 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3806 err_code |= ERR_WARN;
3807
3808 if (*(args[1]) == 0) {
3809 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813
3814 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3815 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3816 file, linenum, args[0]);
3817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
3819 }
3820
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003821 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3822 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3823 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
3826 }
3827
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003828 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003829
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003830 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003831 rule->cond = cond;
3832 rule->srv.name = strdup(args[1]);
3833 LIST_INIT(&rule->list);
3834 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3835 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3836 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003837 else if ((!strcmp(args[0], "force-persist")) ||
3838 (!strcmp(args[0], "ignore-persist"))) {
3839 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003840
3841 if (curproxy == &defproxy) {
3842 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846
3847 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3848 err_code |= ERR_WARN;
3849
Willy Tarreauef6494c2010-01-28 17:12:36 +01003850 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003851 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3852 file, linenum, args[0]);
3853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
3855 }
3856
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003857 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3858 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3859 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003860 err_code |= ERR_ALERT | ERR_FATAL;
3861 goto out;
3862 }
3863
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003864 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3865 * where force-persist is applied.
3866 */
3867 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003868
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003869 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003870 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003871 if (!strcmp(args[0], "force-persist")) {
3872 rule->type = PERSIST_TYPE_FORCE;
3873 } else {
3874 rule->type = PERSIST_TYPE_IGNORE;
3875 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003876 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003877 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003878 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003879 else if (!strcmp(args[0], "stick-table")) {
3880 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003881 struct proxy *other;
3882
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003883 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003884 if (other) {
3885 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3886 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003890
Emeric Brun32da3c42010-09-23 18:39:19 +02003891 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003892 curproxy->table.type = (unsigned int)-1;
3893 while (*args[myidx]) {
3894 const char *err;
3895
3896 if (strcmp(args[myidx], "size") == 0) {
3897 myidx++;
3898 if (!*(args[myidx])) {
3899 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3900 file, linenum, args[myidx-1]);
3901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
3903 }
3904 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3905 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3906 file, linenum, *err, args[myidx-1]);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003910 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003911 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003912 else if (strcmp(args[myidx], "peers") == 0) {
3913 myidx++;
Godbach50523162013-12-11 19:48:57 +08003914 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003915 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3916 file, linenum, args[myidx-1]);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Godbach50523162013-12-11 19:48:57 +08003919 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003920 curproxy->table.peers.name = strdup(args[myidx++]);
3921 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003922 else if (strcmp(args[myidx], "expire") == 0) {
3923 myidx++;
3924 if (!*(args[myidx])) {
3925 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3926 file, linenum, args[myidx-1]);
3927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
3929 }
3930 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3931 if (err) {
3932 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3933 file, linenum, *err, args[myidx-1]);
3934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
3936 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003937 if (val > INT_MAX) {
3938 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3939 file, linenum, val);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003943 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003944 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003945 }
3946 else if (strcmp(args[myidx], "nopurge") == 0) {
3947 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003948 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003949 }
3950 else if (strcmp(args[myidx], "type") == 0) {
3951 myidx++;
3952 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3953 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3954 file, linenum, args[myidx]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003958 /* myidx already points to next arg */
3959 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003960 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003961 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003962 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003963
3964 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003965 nw = args[myidx];
3966 while (*nw) {
3967 /* the "store" keyword supports a comma-separated list */
3968 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003969 sa = NULL; /* store arg */
3970 while (*nw && *nw != ',') {
3971 if (*nw == '(') {
3972 *nw = 0;
3973 sa = ++nw;
3974 while (*nw != ')') {
3975 if (!*nw) {
3976 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3977 file, linenum, args[0], cw);
3978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
3980 }
3981 nw++;
3982 }
3983 *nw = '\0';
3984 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003985 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003986 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003987 if (*nw)
3988 *nw++ = '\0';
3989 type = stktable_get_data_type(cw);
3990 if (type < 0) {
3991 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3992 file, linenum, args[0], cw);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
Willy Tarreauac782882010-06-20 10:41:54 +02003996
3997 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3998 switch (err) {
3999 case PE_NONE: break;
4000 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004001 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4002 file, linenum, args[0], cw);
4003 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004004 break;
4005
4006 case PE_ARG_MISSING:
4007 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4008 file, linenum, args[0], cw);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011
4012 case PE_ARG_NOT_USED:
4013 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4014 file, linenum, args[0], cw);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017
4018 default:
4019 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4020 file, linenum, args[0], cw);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004023 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004024 }
4025 myidx++;
4026 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004027 else {
4028 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4029 file, linenum, args[myidx]);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004032 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004033 }
4034
4035 if (!curproxy->table.size) {
4036 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4037 file, linenum);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041
4042 if (curproxy->table.type == (unsigned int)-1) {
4043 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4044 file, linenum);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
4047 }
4048 }
4049 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004050 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004051 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004052 int myidx = 0;
4053 const char *name = NULL;
4054 int flags;
4055
4056 if (curproxy == &defproxy) {
4057 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061
4062 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4063 err_code |= ERR_WARN;
4064 goto out;
4065 }
4066
4067 myidx++;
4068 if ((strcmp(args[myidx], "store") == 0) ||
4069 (strcmp(args[myidx], "store-request") == 0)) {
4070 myidx++;
4071 flags = STK_IS_STORE;
4072 }
4073 else if (strcmp(args[myidx], "store-response") == 0) {
4074 myidx++;
4075 flags = STK_IS_STORE | STK_ON_RSP;
4076 }
4077 else if (strcmp(args[myidx], "match") == 0) {
4078 myidx++;
4079 flags = STK_IS_MATCH;
4080 }
4081 else if (strcmp(args[myidx], "on") == 0) {
4082 myidx++;
4083 flags = STK_IS_MATCH | STK_IS_STORE;
4084 }
4085 else {
4086 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4087 err_code |= ERR_ALERT | ERR_FATAL;
4088 goto out;
4089 }
4090
4091 if (*(args[myidx]) == 0) {
4092 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004097 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004098 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004100 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
4103 }
4104
4105 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004106 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4107 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4108 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004109 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004110 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004111 goto out;
4112 }
4113 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004114 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4115 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4116 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004117 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004118 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004119 goto out;
4120 }
4121 }
4122
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004123 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004124 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004125
Emeric Brunb982a3d2010-01-04 15:45:53 +01004126 if (strcmp(args[myidx], "table") == 0) {
4127 myidx++;
4128 name = args[myidx++];
4129 }
4130
Willy Tarreauef6494c2010-01-28 17:12:36 +01004131 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004132 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4133 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4134 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004135 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004136 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004137 goto out;
4138 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004139 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004140 else if (*(args[myidx])) {
4141 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4142 file, linenum, args[0], args[myidx]);
4143 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004144 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004145 goto out;
4146 }
Emeric Brun97679e72010-09-23 17:56:44 +02004147 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004148 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004149 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004150 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004151
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004152 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004153 rule->cond = cond;
4154 rule->expr = expr;
4155 rule->flags = flags;
4156 rule->table.name = name ? strdup(name) : NULL;
4157 LIST_INIT(&rule->list);
4158 if (flags & STK_ON_RSP)
4159 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4160 else
4161 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 else if (!strcmp(args[0], "stats")) {
4164 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4165 curproxy->uri_auth = NULL; /* we must detach from the default config */
4166
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004167 if (!*args[1]) {
4168 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004169 } else if (!strcmp(args[1], "admin")) {
4170 struct stats_admin_rule *rule;
4171
4172 if (curproxy == &defproxy) {
4173 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
4177
4178 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4179 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4180 err_code |= ERR_ALERT | ERR_ABORT;
4181 goto out;
4182 }
4183
4184 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4185 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4186 file, linenum, args[0], args[1]);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004190 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4191 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4192 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004197 err_code |= warnif_cond_conflicts(cond,
4198 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4199 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004200
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004201 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004202 rule->cond = cond;
4203 LIST_INIT(&rule->list);
4204 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004205 } else if (!strcmp(args[1], "uri")) {
4206 if (*(args[2]) == 0) {
4207 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4211 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_ABORT;
4213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 }
4215 } else if (!strcmp(args[1], "realm")) {
4216 if (*(args[2]) == 0) {
4217 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4221 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_ABORT;
4223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004225 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004226 unsigned interval;
4227
4228 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4229 if (err) {
4230 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4231 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004234 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4235 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_ABORT;
4237 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004238 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004239 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004240 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004241
4242 if (curproxy == &defproxy) {
4243 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4244 err_code |= ERR_ALERT | ERR_FATAL;
4245 goto out;
4246 }
4247
4248 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4249 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4250 err_code |= ERR_ALERT | ERR_ABORT;
4251 goto out;
4252 }
4253
Willy Tarreauff011f22011-01-06 17:51:27 +01004254 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004255 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004256 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4257 file, linenum, args[0]);
4258 err_code |= ERR_WARN;
4259 }
4260
Willy Tarreauff011f22011-01-06 17:51:27 +01004261 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004262
Willy Tarreauff011f22011-01-06 17:51:27 +01004263 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004264 err_code |= ERR_ALERT | ERR_ABORT;
4265 goto out;
4266 }
4267
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004268 err_code |= warnif_cond_conflicts(rule->cond,
4269 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4270 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004271 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004272
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 } else if (!strcmp(args[1], "auth")) {
4274 if (*(args[2]) == 0) {
4275 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_ABORT;
4281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 }
4283 } else if (!strcmp(args[1], "scope")) {
4284 if (*(args[2]) == 0) {
4285 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4289 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_ALERT | ERR_ABORT;
4291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 }
4293 } else if (!strcmp(args[1], "enable")) {
4294 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_ABORT;
4297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004299 } else if (!strcmp(args[1], "hide-version")) {
4300 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_ABORT;
4303 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004304 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004305 } else if (!strcmp(args[1], "show-legends")) {
4306 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4307 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4308 err_code |= ERR_ALERT | ERR_ABORT;
4309 goto out;
4310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004311 } else if (!strcmp(args[1], "show-node")) {
4312
4313 if (*args[2]) {
4314 int i;
4315 char c;
4316
4317 for (i=0; args[2][i]; i++) {
4318 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004319 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4320 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004321 break;
4322 }
4323
4324 if (!i || args[2][i]) {
4325 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4326 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4327 file, linenum, args[0], args[1]);
4328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
4330 }
4331 }
4332
4333 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4334 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4335 err_code |= ERR_ALERT | ERR_ABORT;
4336 goto out;
4337 }
4338 } else if (!strcmp(args[1], "show-desc")) {
4339 char *desc = NULL;
4340
4341 if (*args[2]) {
4342 int i, len=0;
4343 char *d;
4344
Willy Tarreau348acfe2014-04-14 15:00:39 +02004345 for (i = 2; *args[i]; i++)
4346 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004347
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004348 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004349
Willy Tarreau348acfe2014-04-14 15:00:39 +02004350 d += snprintf(d, desc + len - d, "%s", args[2]);
4351 for (i = 3; *args[i]; i++)
4352 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004353 }
4354
4355 if (!*args[2] && !global.desc)
4356 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4357 file, linenum, args[1]);
4358 else {
4359 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4360 free(desc);
4361 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4362 err_code |= ERR_ALERT | ERR_ABORT;
4363 goto out;
4364 }
4365 free(desc);
4366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004368stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004369 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 +01004370 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 }
4374 }
4375 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004376 int optnum;
4377
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004378 if (*(args[1]) == '\0') {
4379 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004384
4385 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4386 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004387 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4388 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4389 file, linenum, cfg_opts[optnum].name);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004393 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4394 goto out;
4395
Willy Tarreau93893792009-07-23 13:19:11 +02004396 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4397 err_code |= ERR_WARN;
4398 goto out;
4399 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004400
Willy Tarreau3842f002009-06-14 11:39:52 +02004401 curproxy->no_options &= ~cfg_opts[optnum].val;
4402 curproxy->options &= ~cfg_opts[optnum].val;
4403
4404 switch (kwm) {
4405 case KWM_STD:
4406 curproxy->options |= cfg_opts[optnum].val;
4407 break;
4408 case KWM_NO:
4409 curproxy->no_options |= cfg_opts[optnum].val;
4410 break;
4411 case KWM_DEF: /* already cleared */
4412 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004413 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004414
Willy Tarreau93893792009-07-23 13:19:11 +02004415 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004416 }
4417 }
4418
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004419 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4420 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004421 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4422 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4423 file, linenum, cfg_opts2[optnum].name);
4424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
4426 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004427 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4428 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004429 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4430 err_code |= ERR_WARN;
4431 goto out;
4432 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004433
Willy Tarreau3842f002009-06-14 11:39:52 +02004434 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4435 curproxy->options2 &= ~cfg_opts2[optnum].val;
4436
4437 switch (kwm) {
4438 case KWM_STD:
4439 curproxy->options2 |= cfg_opts2[optnum].val;
4440 break;
4441 case KWM_NO:
4442 curproxy->no_options2 |= cfg_opts2[optnum].val;
4443 break;
4444 case KWM_DEF: /* already cleared */
4445 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004446 }
Willy Tarreau93893792009-07-23 13:19:11 +02004447 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004448 }
4449 }
4450
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004451 /* HTTP options override each other. They can be cancelled using
4452 * "no option xxx" which only switches to default mode if the mode
4453 * was this one (useful for cancelling options set in defaults
4454 * sections).
4455 */
4456 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004457 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4458 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004459 if (kwm == KWM_STD) {
4460 curproxy->options &= ~PR_O_HTTP_MODE;
4461 curproxy->options |= PR_O_HTTP_PCL;
4462 goto out;
4463 }
4464 else if (kwm == KWM_NO) {
4465 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4466 curproxy->options &= ~PR_O_HTTP_MODE;
4467 goto out;
4468 }
4469 }
4470 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004471 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4472 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004473 if (kwm == KWM_STD) {
4474 curproxy->options &= ~PR_O_HTTP_MODE;
4475 curproxy->options |= PR_O_HTTP_FCL;
4476 goto out;
4477 }
4478 else if (kwm == KWM_NO) {
4479 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4480 curproxy->options &= ~PR_O_HTTP_MODE;
4481 goto out;
4482 }
4483 }
4484 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004485 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4486 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004487 if (kwm == KWM_STD) {
4488 curproxy->options &= ~PR_O_HTTP_MODE;
4489 curproxy->options |= PR_O_HTTP_SCL;
4490 goto out;
4491 }
4492 else if (kwm == KWM_NO) {
4493 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4494 curproxy->options &= ~PR_O_HTTP_MODE;
4495 goto out;
4496 }
4497 }
4498 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004499 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4500 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004501 if (kwm == KWM_STD) {
4502 curproxy->options &= ~PR_O_HTTP_MODE;
4503 curproxy->options |= PR_O_HTTP_KAL;
4504 goto out;
4505 }
4506 else if (kwm == KWM_NO) {
4507 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4508 curproxy->options &= ~PR_O_HTTP_MODE;
4509 goto out;
4510 }
4511 }
4512 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004513 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4514 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004515 if (kwm == KWM_STD) {
4516 curproxy->options &= ~PR_O_HTTP_MODE;
4517 curproxy->options |= PR_O_HTTP_TUN;
4518 goto out;
4519 }
4520 else if (kwm == KWM_NO) {
4521 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4522 curproxy->options &= ~PR_O_HTTP_MODE;
4523 goto out;
4524 }
4525 }
4526
Joseph Lynch726ab712015-05-11 23:25:34 -07004527 /* Redispatch can take an integer argument that control when the
4528 * resispatch occurs. All values are relative to the retries option.
4529 * This can be cancelled using "no option xxx".
4530 */
4531 if (strcmp(args[1], "redispatch") == 0) {
4532 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4533 err_code |= ERR_WARN;
4534 goto out;
4535 }
4536
4537 curproxy->no_options &= ~PR_O_REDISP;
4538 curproxy->options &= ~PR_O_REDISP;
4539
4540 switch (kwm) {
4541 case KWM_STD:
4542 curproxy->options |= PR_O_REDISP;
4543 curproxy->redispatch_after = -1;
4544 if(*args[2]) {
4545 curproxy->redispatch_after = atol(args[2]);
4546 }
4547 break;
4548 case KWM_NO:
4549 curproxy->no_options |= PR_O_REDISP;
4550 curproxy->redispatch_after = 0;
4551 break;
4552 case KWM_DEF: /* already cleared */
4553 break;
4554 }
4555 goto out;
4556 }
4557
Willy Tarreau3842f002009-06-14 11:39:52 +02004558 if (kwm != KWM_STD) {
4559 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004560 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004563 }
4564
Emeric Brun3a058f32009-06-30 18:26:00 +02004565 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004566 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004568 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004569 if (*(args[2]) != '\0') {
4570 if (!strcmp(args[2], "clf")) {
4571 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004572 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004573 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004574 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004575 err_code |= ERR_ALERT | ERR_FATAL;
4576 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004577 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004578 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4579 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004580 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004581 if (curproxy->conf.logformat_string != default_http_log_format &&
4582 curproxy->conf.logformat_string != default_tcp_log_format &&
4583 curproxy->conf.logformat_string != clf_http_log_format)
4584 free(curproxy->conf.logformat_string);
4585 curproxy->conf.logformat_string = logformat;
4586
4587 free(curproxy->conf.lfs_file);
4588 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4589 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004590 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004591 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004593 if (curproxy->conf.logformat_string != default_http_log_format &&
4594 curproxy->conf.logformat_string != default_tcp_log_format &&
4595 curproxy->conf.logformat_string != clf_http_log_format)
4596 free(curproxy->conf.logformat_string);
4597 curproxy->conf.logformat_string = default_tcp_log_format;
4598
4599 free(curproxy->conf.lfs_file);
4600 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4601 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004602
4603 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4604 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004607 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004608 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004610
William Lallemanddf1425a2015-04-28 20:17:49 +02004611 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4612 goto out;
4613
Willy Tarreau13943ab2006-12-31 00:24:10 +01004614 if (curproxy->cap & PR_CAP_FE)
4615 curproxy->options |= PR_O_TCP_CLI_KA;
4616 if (curproxy->cap & PR_CAP_BE)
4617 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 }
4619 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004620 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_WARN;
4622
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004624 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004625 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004626 curproxy->options2 &= ~PR_O2_CHK_ANY;
4627 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 if (!*args[2]) { /* no argument */
4629 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4630 curproxy->check_len = strlen(DEF_CHECK_REQ);
4631 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004632 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004633 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004635 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004637 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004638 if (*args[4])
4639 reqlen += strlen(args[4]);
4640 else
4641 reqlen += strlen("HTTP/1.0");
4642
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004643 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004644 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004645 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004647 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4648 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004649 }
4650 else if (!strcmp(args[1], "ssl-hello-chk")) {
4651 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004652 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004653 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004654
Willy Tarreaua534fea2008-08-03 12:19:50 +02004655 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004656 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004657 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004658 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004659
4660 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 }
Willy Tarreau23677902007-05-08 23:50:35 +02004663 else if (!strcmp(args[1], "smtpchk")) {
4664 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004665 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004666 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004667 curproxy->options2 &= ~PR_O2_CHK_ANY;
4668 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004669
4670 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4671 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4672 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4673 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4674 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4675 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004676 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004677 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4678 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4679 } else {
4680 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4681 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4682 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4683 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4684 }
4685 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004686 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4687 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004688 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004689 else if (!strcmp(args[1], "pgsql-check")) {
4690 /* use PostgreSQL request to check servers' health */
4691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4692 err_code |= ERR_WARN;
4693
4694 free(curproxy->check_req);
4695 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004696 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004697 curproxy->options2 |= PR_O2_PGSQL_CHK;
4698
4699 if (*(args[2])) {
4700 int cur_arg = 2;
4701
4702 while (*(args[cur_arg])) {
4703 if (strcmp(args[cur_arg], "user") == 0) {
4704 char * packet;
4705 uint32_t packet_len;
4706 uint32_t pv;
4707
4708 /* suboption header - needs additional argument for it */
4709 if (*(args[cur_arg+1]) == 0) {
4710 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4711 file, linenum, args[0], args[1], args[cur_arg]);
4712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714 }
4715
4716 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4717 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4718 pv = htonl(0x30000); /* protocol version 3.0 */
4719
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004720 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004721
4722 memcpy(packet + 4, &pv, 4);
4723
4724 /* copy "user" */
4725 memcpy(packet + 8, "user", 4);
4726
4727 /* copy username */
4728 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4729
4730 free(curproxy->check_req);
4731 curproxy->check_req = packet;
4732 curproxy->check_len = packet_len;
4733
4734 packet_len = htonl(packet_len);
4735 memcpy(packet, &packet_len, 4);
4736 cur_arg += 2;
4737 } else {
4738 /* unknown suboption - catchall */
4739 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4740 file, linenum, args[0], args[1]);
4741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
4744 } /* end while loop */
4745 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004746 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4747 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004748 }
4749
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004750 else if (!strcmp(args[1], "redis-check")) {
4751 /* use REDIS PING request to check servers' health */
4752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4753 err_code |= ERR_WARN;
4754
4755 free(curproxy->check_req);
4756 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004757 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004758 curproxy->options2 |= PR_O2_REDIS_CHK;
4759
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004760 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004761 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4762 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004763
4764 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4765 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004766 }
4767
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004768 else if (!strcmp(args[1], "mysql-check")) {
4769 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004770 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4771 err_code |= ERR_WARN;
4772
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004773 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004774 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004775 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004776 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004777
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004778 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004779 * const char mysql40_client_auth_pkt[] = {
4780 * "\x0e\x00\x00" // packet length
4781 * "\x01" // packet number
4782 * "\x00\x00" // client capabilities
4783 * "\x00\x00\x01" // max packet
4784 * "haproxy\x00" // username (null terminated string)
4785 * "\x00" // filler (always 0x00)
4786 * "\x01\x00\x00" // packet length
4787 * "\x00" // packet number
4788 * "\x01" // COM_QUIT command
4789 * };
4790 */
4791
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004792 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4793 * const char mysql41_client_auth_pkt[] = {
4794 * "\x0e\x00\x00\" // packet length
4795 * "\x01" // packet number
4796 * "\x00\x00\x00\x00" // client capabilities
4797 * "\x00\x00\x00\x01" // max packet
4798 * "\x21" // character set (UTF-8)
4799 * char[23] // All zeroes
4800 * "haproxy\x00" // username (null terminated string)
4801 * "\x00" // filler (always 0x00)
4802 * "\x01\x00\x00" // packet length
4803 * "\x00" // packet number
4804 * "\x01" // COM_QUIT command
4805 * };
4806 */
4807
4808
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004809 if (*(args[2])) {
4810 int cur_arg = 2;
4811
4812 while (*(args[cur_arg])) {
4813 if (strcmp(args[cur_arg], "user") == 0) {
4814 char *mysqluser;
4815 int packetlen, reqlen, userlen;
4816
4817 /* suboption header - needs additional argument for it */
4818 if (*(args[cur_arg+1]) == 0) {
4819 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4820 file, linenum, args[0], args[1], args[cur_arg]);
4821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823 }
4824 mysqluser = args[cur_arg + 1];
4825 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004826
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004827 if (*(args[cur_arg+2])) {
4828 if (!strcmp(args[cur_arg+2], "post-41")) {
4829 packetlen = userlen + 7 + 27;
4830 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004831
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004832 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004833 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004834 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004835
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004836 snprintf(curproxy->check_req, 4, "%c%c%c",
4837 ((unsigned char) packetlen & 0xff),
4838 ((unsigned char) (packetlen >> 8) & 0xff),
4839 ((unsigned char) (packetlen >> 16) & 0xff));
4840
4841 curproxy->check_req[3] = 1;
4842 curproxy->check_req[5] = 130;
4843 curproxy->check_req[11] = 1;
4844 curproxy->check_req[12] = 33;
4845 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4846 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4847 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4848 cur_arg += 3;
4849 } else {
4850 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854 } else {
4855 packetlen = userlen + 7;
4856 reqlen = packetlen + 9;
4857
4858 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004859 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004860 curproxy->check_len = reqlen;
4861
4862 snprintf(curproxy->check_req, 4, "%c%c%c",
4863 ((unsigned char) packetlen & 0xff),
4864 ((unsigned char) (packetlen >> 8) & 0xff),
4865 ((unsigned char) (packetlen >> 16) & 0xff));
4866
4867 curproxy->check_req[3] = 1;
4868 curproxy->check_req[5] = 128;
4869 curproxy->check_req[8] = 1;
4870 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4871 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4872 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4873 cur_arg += 2;
4874 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004875 } else {
4876 /* unknown suboption - catchall */
4877 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4878 file, linenum, args[0], args[1]);
4879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
4881 }
4882 } /* end while loop */
4883 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004884 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004885 else if (!strcmp(args[1], "ldap-check")) {
4886 /* use LDAP request to check servers' health */
4887 free(curproxy->check_req);
4888 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004889 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004890 curproxy->options2 |= PR_O2_LDAP_CHK;
4891
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004892 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004893 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4894 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004895 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4896 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004897 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004898 else if (!strcmp(args[1], "spop-check")) {
4899 if (curproxy == &defproxy) {
4900 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4901 file, linenum, args[0], args[1]);
4902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
4904 }
4905 if (curproxy->cap & PR_CAP_FE) {
4906 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4907 file, linenum, args[0], args[1]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
4911
4912 /* use SPOE request to check servers' health */
4913 free(curproxy->check_req);
4914 curproxy->check_req = NULL;
4915 curproxy->options2 &= ~PR_O2_CHK_ANY;
4916 curproxy->options2 |= PR_O2_SPOP_CHK;
4917
4918 if (prepare_spoe_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
4919 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
4922 }
4923 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4924 goto out;
4925 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004926 else if (!strcmp(args[1], "tcp-check")) {
4927 /* use raw TCPCHK send/expect to check servers' health */
4928 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4929 err_code |= ERR_WARN;
4930
4931 free(curproxy->check_req);
4932 curproxy->check_req = NULL;
4933 curproxy->options2 &= ~PR_O2_CHK_ANY;
4934 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004935 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4936 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004937 }
Simon Horman98637e52014-06-20 12:30:16 +09004938 else if (!strcmp(args[1], "external-check")) {
4939 /* excute an external command to check servers' health */
4940 free(curproxy->check_req);
4941 curproxy->check_req = NULL;
4942 curproxy->options2 &= ~PR_O2_CHK_ANY;
4943 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004944 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4945 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004946 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004947 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004948 int cur_arg;
4949
4950 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4951 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004952 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004953
Willy Tarreau87cf5142011-08-19 22:57:24 +02004954 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004955
4956 free(curproxy->fwdfor_hdr_name);
4957 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4958 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4959
4960 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4961 cur_arg = 2;
4962 while (*(args[cur_arg])) {
4963 if (!strcmp(args[cur_arg], "except")) {
4964 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004965 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004966 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4967 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004970 }
4971 /* flush useless bits */
4972 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004973 cur_arg += 2;
4974 } else if (!strcmp(args[cur_arg], "header")) {
4975 /* suboption header - needs additional argument for it */
4976 if (*(args[cur_arg+1]) == 0) {
4977 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4978 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004981 }
4982 free(curproxy->fwdfor_hdr_name);
4983 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4984 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4985 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004986 } else if (!strcmp(args[cur_arg], "if-none")) {
4987 curproxy->options &= ~PR_O_FF_ALWAYS;
4988 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004989 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004990 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004991 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004992 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004995 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004996 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004997 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004998 else if (!strcmp(args[1], "originalto")) {
4999 int cur_arg;
5000
5001 /* insert x-original-to field, but not for the IP address listed as an except.
5002 * set default options (ie: bitfield, header name, etc)
5003 */
5004
5005 curproxy->options |= PR_O_ORGTO;
5006
5007 free(curproxy->orgto_hdr_name);
5008 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5009 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5010
Willy Tarreau87cf5142011-08-19 22:57:24 +02005011 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005012 cur_arg = 2;
5013 while (*(args[cur_arg])) {
5014 if (!strcmp(args[cur_arg], "except")) {
5015 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005016 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 +02005017 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5018 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005021 }
5022 /* flush useless bits */
5023 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5024 cur_arg += 2;
5025 } else if (!strcmp(args[cur_arg], "header")) {
5026 /* suboption header - needs additional argument for it */
5027 if (*(args[cur_arg+1]) == 0) {
5028 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5029 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005032 }
5033 free(curproxy->orgto_hdr_name);
5034 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5035 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5036 cur_arg += 2;
5037 } else {
5038 /* unknown suboption - catchall */
5039 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5040 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005043 }
5044 } /* end while loop */
5045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 else {
5047 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
Willy Tarreau93893792009-07-23 13:19:11 +02005051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005053 else if (!strcmp(args[0], "default_backend")) {
5054 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005056
5057 if (*(args[1]) == 0) {
5058 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005061 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005062 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005063 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005064
5065 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5066 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005069 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005071
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005072 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5073 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 +01005074 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005075 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 /* enable reconnections to dispatch */
5077 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005078
5079 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005082 else if (!strcmp(args[0], "http-reuse")) {
5083 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5084 err_code |= ERR_WARN;
5085
5086 if (strcmp(args[1], "never") == 0) {
5087 /* enable a graceful server shutdown on an HTTP 404 response */
5088 curproxy->options &= ~PR_O_REUSE_MASK;
5089 curproxy->options |= PR_O_REUSE_NEVR;
5090 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5091 goto out;
5092 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005093 else if (strcmp(args[1], "safe") == 0) {
5094 /* enable a graceful server shutdown on an HTTP 404 response */
5095 curproxy->options &= ~PR_O_REUSE_MASK;
5096 curproxy->options |= PR_O_REUSE_SAFE;
5097 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5098 goto out;
5099 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005100 else if (strcmp(args[1], "aggressive") == 0) {
5101 curproxy->options &= ~PR_O_REUSE_MASK;
5102 curproxy->options |= PR_O_REUSE_AGGR;
5103 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5104 goto out;
5105 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005106 else if (strcmp(args[1], "always") == 0) {
5107 /* enable a graceful server shutdown on an HTTP 404 response */
5108 curproxy->options &= ~PR_O_REUSE_MASK;
5109 curproxy->options |= PR_O_REUSE_ALWS;
5110 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5111 goto out;
5112 }
5113 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005114 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005119 else if (!strcmp(args[0], "http-check")) {
5120 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005122
5123 if (strcmp(args[1], "disable-on-404") == 0) {
5124 /* enable a graceful server shutdown on an HTTP 404 response */
5125 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005126 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5127 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005128 }
Willy Tarreauef781042010-01-27 11:53:01 +01005129 else if (strcmp(args[1], "send-state") == 0) {
5130 /* enable emission of the apparent state of a server in HTTP checks */
5131 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005132 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5133 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005134 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005135 else if (strcmp(args[1], "expect") == 0) {
5136 const char *ptr_arg;
5137 int cur_arg;
5138
5139 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5140 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
5143 }
5144
5145 cur_arg = 2;
5146 /* consider exclamation marks, sole or at the beginning of a word */
5147 while (*(ptr_arg = args[cur_arg])) {
5148 while (*ptr_arg == '!') {
5149 curproxy->options2 ^= PR_O2_EXP_INV;
5150 ptr_arg++;
5151 }
5152 if (*ptr_arg)
5153 break;
5154 cur_arg++;
5155 }
5156 /* now ptr_arg points to the beginning of a word past any possible
5157 * exclamation mark, and cur_arg is the argument which holds this word.
5158 */
5159 if (strcmp(ptr_arg, "status") == 0) {
5160 if (!*(args[cur_arg + 1])) {
5161 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5162 file, linenum, args[0], args[1], ptr_arg);
5163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
5165 }
5166 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005167 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005168 curproxy->expect_str = strdup(args[cur_arg + 1]);
5169 }
5170 else if (strcmp(ptr_arg, "string") == 0) {
5171 if (!*(args[cur_arg + 1])) {
5172 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5173 file, linenum, args[0], args[1], ptr_arg);
5174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
5176 }
5177 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005178 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005179 curproxy->expect_str = strdup(args[cur_arg + 1]);
5180 }
5181 else if (strcmp(ptr_arg, "rstatus") == 0) {
5182 if (!*(args[cur_arg + 1])) {
5183 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5184 file, linenum, args[0], args[1], ptr_arg);
5185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
5187 }
5188 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005189 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005190 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005191 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005192 free(curproxy->expect_regex);
5193 curproxy->expect_regex = NULL;
5194 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005195 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005196 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5197 error = NULL;
5198 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5199 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5200 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5201 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205 }
5206 else if (strcmp(ptr_arg, "rstring") == 0) {
5207 if (!*(args[cur_arg + 1])) {
5208 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5209 file, linenum, args[0], args[1], ptr_arg);
5210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
5212 }
5213 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005214 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005215 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005216 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005217 free(curproxy->expect_regex);
5218 curproxy->expect_regex = NULL;
5219 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005220 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005221 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5222 error = NULL;
5223 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5224 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5225 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5226 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229 }
5230 }
5231 else {
5232 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5233 file, linenum, args[0], args[1], ptr_arg);
5234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
5237 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005238 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005239 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 +02005240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005242 }
5243 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005244 else if (!strcmp(args[0], "tcp-check")) {
5245 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5246 err_code |= ERR_WARN;
5247
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005248 if (strcmp(args[1], "comment") == 0) {
5249 int cur_arg;
5250 struct tcpcheck_rule *tcpcheck;
5251
5252 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005253 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005254 tcpcheck->action = TCPCHK_ACT_COMMENT;
5255
5256 if (!*args[cur_arg + 1]) {
5257 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5258 file, linenum, args[cur_arg]);
5259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261 }
5262
5263 tcpcheck->comment = strdup(args[cur_arg + 1]);
5264
5265 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005266 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5267 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005268 }
5269 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005270 const char *ptr_arg;
5271 int cur_arg;
5272 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005273
5274 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005275 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5276 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5277 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5278 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5279 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005280
Willy Tarreau5581c272015-05-13 12:24:53 +02005281 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5282 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5283 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5284 file, linenum);
5285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005287 }
5288
5289 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005290 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005291 tcpcheck->action = TCPCHK_ACT_CONNECT;
5292
5293 /* parsing each parameters to fill up the rule */
5294 while (*(ptr_arg = args[cur_arg])) {
5295 /* tcp port */
5296 if (strcmp(args[cur_arg], "port") == 0) {
5297 if ( (atol(args[cur_arg + 1]) > 65535) ||
5298 (atol(args[cur_arg + 1]) < 1) ){
5299 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5300 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 }
5304 tcpcheck->port = atol(args[cur_arg + 1]);
5305 cur_arg += 2;
5306 }
5307 /* send proxy protocol */
5308 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5309 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5310 cur_arg++;
5311 }
5312#ifdef USE_OPENSSL
5313 else if (strcmp(args[cur_arg], "ssl") == 0) {
5314 curproxy->options |= PR_O_TCPCHK_SSL;
5315 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5316 cur_arg++;
5317 }
5318#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005319 /* comment for this tcpcheck line */
5320 else if (strcmp(args[cur_arg], "comment") == 0) {
5321 if (!*args[cur_arg + 1]) {
5322 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5323 file, linenum, args[cur_arg]);
5324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
5326 }
5327 tcpcheck->comment = strdup(args[cur_arg + 1]);
5328 cur_arg += 2;
5329 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005330 else {
5331#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005332 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 +01005333#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005334 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 +01005335#endif /* USE_OPENSSL */
5336 file, linenum, args[0], args[1], args[cur_arg]);
5337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
5339 }
5340
5341 }
5342
5343 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5344 }
5345 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005346 if (! *(args[2]) ) {
5347 /* SEND string expected */
5348 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5349 file, linenum, args[0], args[1], args[2]);
5350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 } else {
5353 struct tcpcheck_rule *tcpcheck;
5354
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005355 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005356
5357 tcpcheck->action = TCPCHK_ACT_SEND;
5358 tcpcheck->string_len = strlen(args[2]);
5359 tcpcheck->string = strdup(args[2]);
5360 tcpcheck->expect_regex = NULL;
5361
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005362 /* comment for this tcpcheck line */
5363 if (strcmp(args[3], "comment") == 0) {
5364 if (!*args[4]) {
5365 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5366 file, linenum, args[3]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370 tcpcheck->comment = strdup(args[4]);
5371 }
5372
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005373 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5374 }
5375 }
5376 else if (strcmp(args[1], "send-binary") == 0) {
5377 if (! *(args[2]) ) {
5378 /* SEND binary string expected */
5379 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5380 file, linenum, args[0], args[1], args[2]);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 } else {
5384 struct tcpcheck_rule *tcpcheck;
5385 char *err = NULL;
5386
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005387 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005388
5389 tcpcheck->action = TCPCHK_ACT_SEND;
5390 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5391 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5392 file, linenum, args[0], args[1], args[2], err);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
5396 tcpcheck->expect_regex = NULL;
5397
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005398 /* comment for this tcpcheck line */
5399 if (strcmp(args[3], "comment") == 0) {
5400 if (!*args[4]) {
5401 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5402 file, linenum, args[3]);
5403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
5405 }
5406 tcpcheck->comment = strdup(args[4]);
5407 }
5408
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005409 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5410 }
5411 }
5412 else if (strcmp(args[1], "expect") == 0) {
5413 const char *ptr_arg;
5414 int cur_arg;
5415 int inverse = 0;
5416
5417 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5418 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
5421 }
5422
5423 cur_arg = 2;
5424 /* consider exclamation marks, sole or at the beginning of a word */
5425 while (*(ptr_arg = args[cur_arg])) {
5426 while (*ptr_arg == '!') {
5427 inverse = !inverse;
5428 ptr_arg++;
5429 }
5430 if (*ptr_arg)
5431 break;
5432 cur_arg++;
5433 }
5434 /* now ptr_arg points to the beginning of a word past any possible
5435 * exclamation mark, and cur_arg is the argument which holds this word.
5436 */
5437 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005438 struct tcpcheck_rule *tcpcheck;
5439 char *err = NULL;
5440
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005441 if (!*(args[cur_arg + 1])) {
5442 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5443 file, linenum, args[0], args[1], ptr_arg);
5444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005447
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005448 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005449
5450 tcpcheck->action = TCPCHK_ACT_EXPECT;
5451 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5452 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5453 file, linenum, args[0], args[1], args[2], err);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457 tcpcheck->expect_regex = NULL;
5458 tcpcheck->inverse = inverse;
5459
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005460 /* tcpcheck comment */
5461 cur_arg += 2;
5462 if (strcmp(args[cur_arg], "comment") == 0) {
5463 if (!*args[cur_arg + 1]) {
5464 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5465 file, linenum, args[cur_arg + 1]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
5469 tcpcheck->comment = strdup(args[cur_arg + 1]);
5470 }
5471
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005472 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5473 }
5474 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005475 struct tcpcheck_rule *tcpcheck;
5476
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005477 if (!*(args[cur_arg + 1])) {
5478 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5479 file, linenum, args[0], args[1], ptr_arg);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
5482 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005483
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005484 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005485
5486 tcpcheck->action = TCPCHK_ACT_EXPECT;
5487 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5488 tcpcheck->string = strdup(args[cur_arg + 1]);
5489 tcpcheck->expect_regex = NULL;
5490 tcpcheck->inverse = inverse;
5491
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005492 /* tcpcheck comment */
5493 cur_arg += 2;
5494 if (strcmp(args[cur_arg], "comment") == 0) {
5495 if (!*args[cur_arg + 1]) {
5496 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5497 file, linenum, args[cur_arg + 1]);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
5500 }
5501 tcpcheck->comment = strdup(args[cur_arg + 1]);
5502 }
5503
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005504 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5505 }
5506 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005507 struct tcpcheck_rule *tcpcheck;
5508
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005509 if (!*(args[cur_arg + 1])) {
5510 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5511 file, linenum, args[0], args[1], ptr_arg);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005515
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005516 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005517
5518 tcpcheck->action = TCPCHK_ACT_EXPECT;
5519 tcpcheck->string_len = 0;
5520 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005521 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5522 error = NULL;
5523 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5524 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5525 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5526 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
5530 tcpcheck->inverse = inverse;
5531
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005532 /* tcpcheck comment */
5533 cur_arg += 2;
5534 if (strcmp(args[cur_arg], "comment") == 0) {
5535 if (!*args[cur_arg + 1]) {
5536 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5537 file, linenum, args[cur_arg + 1]);
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
5541 tcpcheck->comment = strdup(args[cur_arg + 1]);
5542 }
5543
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005544 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5545 }
5546 else {
5547 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5548 file, linenum, args[0], args[1], ptr_arg);
5549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
5551 }
5552 }
5553 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005554 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005555 err_code |= ERR_ALERT | ERR_FATAL;
5556 goto out;
5557 }
5558 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005559 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005560 if (curproxy == &defproxy) {
5561 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005564 }
5565
Willy Tarreaub80c2302007-11-30 20:51:32 +01005566 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005568
5569 if (strcmp(args[1], "fail") == 0) {
5570 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005571 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005572 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5573 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005576 }
5577
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005578 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5579 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5580 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005583 }
5584 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5585 }
5586 else {
5587 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005590 }
5591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592#ifdef TPROXY
5593 else if (!strcmp(args[0], "transparent")) {
5594 /* enable transparent proxy connections */
5595 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005596 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 }
5599#endif
5600 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005601 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005602 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005603
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 if (*(args[1]) == 0) {
5605 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005606 err_code |= ERR_ALERT | ERR_FATAL;
5607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 }
5609 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005610 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005613 else if (!strcmp(args[0], "backlog")) { /* backlog */
5614 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005615 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005616
5617 if (*(args[1]) == 0) {
5618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005621 }
5622 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005623 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5624 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005625 }
Willy Tarreau86034312006-12-29 00:10:33 +01005626 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005627 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005629
Willy Tarreau86034312006-12-29 00:10:33 +01005630 if (*(args[1]) == 0) {
5631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005634 }
5635 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005636 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5637 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5640 if (*(args[1]) == 0) {
5641 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005645 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5646 if (err) {
5647 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5648 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005649 err_code |= ERR_ALERT | ERR_FATAL;
5650 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005651 }
5652 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005653 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
5656 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005657 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005658 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005659 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005660
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 if (curproxy == &defproxy) {
5662 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005666 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005667 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005668
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005669 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005670 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005671 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005672 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005673 goto out;
5674 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005675
5676 proto = protocol_by_family(sk->ss_family);
5677 if (!proto || !proto->connect) {
5678 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5679 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
5683
5684 if (port1 != port2) {
5685 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5686 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005690
5691 if (!port1) {
5692 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5693 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005694 err_code |= ERR_ALERT | ERR_FATAL;
5695 goto out;
5696 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005697
William Lallemanddf1425a2015-04-28 20:17:49 +02005698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5699 goto out;
5700
Willy Tarreaud5191e72010-02-09 20:50:45 +01005701 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005702 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 }
5704 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005705 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005706 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005707
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005708 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5709 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005714 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005715 /**
5716 * The syntax for hash-type config element is
5717 * hash-type {map-based|consistent} [[<algo>] avalanche]
5718 *
5719 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5720 */
5721 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005722
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005723 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5724 err_code |= ERR_WARN;
5725
5726 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005727 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5728 }
5729 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005730 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5731 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005732 else if (strcmp(args[1], "avalanche") == 0) {
5733 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]);
5734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005736 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005737 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005738 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005739 err_code |= ERR_ALERT | ERR_FATAL;
5740 goto out;
5741 }
Bhaskar98634f02013-10-29 23:30:51 -04005742
5743 /* set the hash function to use */
5744 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005745 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005746 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005747
5748 /* if consistent with no argument, then avalanche modifier is also applied */
5749 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5750 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005751 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005752 /* set the hash function */
5753 if (!strcmp(args[2], "sdbm")) {
5754 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5755 }
5756 else if (!strcmp(args[2], "djb2")) {
5757 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005758 }
5759 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005760 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005761 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005762 else if (!strcmp(args[2], "crc32")) {
5763 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5764 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005765 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005766 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 -05005767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
5769 }
5770
5771 /* set the hash modifier */
5772 if (!strcmp(args[3], "avalanche")) {
5773 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5774 }
5775 else if (*args[3]) {
5776 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5777 err_code |= ERR_ALERT | ERR_FATAL;
5778 goto out;
5779 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005780 }
William Lallemanda73203e2012-03-12 12:48:57 +01005781 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005782 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5783 if (*(args[1]) == 0) {
5784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
5787 }
5788 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5789 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5790 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5791 err_code |= ERR_ALERT | ERR_FATAL;
5792 goto out;
5793 }
5794 }
William Lallemanda73203e2012-03-12 12:48:57 +01005795 else if (strcmp(args[0], "unique-id-format") == 0) {
5796 if (!*(args[1])) {
5797 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
5800 }
William Lallemand3203ff42012-11-11 17:30:56 +01005801 if (*(args[2])) {
5802 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5803 err_code |= ERR_ALERT | ERR_FATAL;
5804 goto out;
5805 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005806 free(curproxy->conf.uniqueid_format_string);
5807 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005808
Willy Tarreau62a61232013-04-12 18:13:46 +02005809 free(curproxy->conf.uif_file);
5810 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5811 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005812 }
William Lallemanda73203e2012-03-12 12:48:57 +01005813
5814 else if (strcmp(args[0], "unique-id-header") == 0) {
5815 if (!*(args[1])) {
5816 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
5819 }
5820 free(curproxy->header_unique_id);
5821 curproxy->header_unique_id = strdup(args[1]);
5822 }
5823
William Lallemand723b73a2012-02-08 16:37:49 +01005824 else if (strcmp(args[0], "log-format") == 0) {
5825 if (!*(args[1])) {
5826 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
5829 }
William Lallemand3203ff42012-11-11 17:30:56 +01005830 if (*(args[2])) {
5831 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5832 err_code |= ERR_ALERT | ERR_FATAL;
5833 goto out;
5834 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005835
Willy Tarreau62a61232013-04-12 18:13:46 +02005836 if (curproxy->conf.logformat_string != default_http_log_format &&
5837 curproxy->conf.logformat_string != default_tcp_log_format &&
5838 curproxy->conf.logformat_string != clf_http_log_format)
5839 free(curproxy->conf.logformat_string);
5840 curproxy->conf.logformat_string = strdup(args[1]);
5841
5842 free(curproxy->conf.lfs_file);
5843 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5844 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005845
5846 /* get a chance to improve log-format error reporting by
5847 * reporting the correct line-number when possible.
5848 */
5849 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5850 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5851 file, linenum, curproxy->id);
5852 err_code |= ERR_WARN;
5853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005855 else if (!strcmp(args[0], "log-format-sd")) {
5856 if (!*(args[1])) {
5857 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5858 err_code |= ERR_ALERT | ERR_FATAL;
5859 goto out;
5860 }
5861 if (*(args[2])) {
5862 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5863 err_code |= ERR_ALERT | ERR_FATAL;
5864 goto out;
5865 }
5866
5867 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5868 free(curproxy->conf.logformat_sd_string);
5869 curproxy->conf.logformat_sd_string = strdup(args[1]);
5870
5871 free(curproxy->conf.lfsd_file);
5872 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5873 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5874
5875 /* get a chance to improve log-format-sd error reporting by
5876 * reporting the correct line-number when possible.
5877 */
5878 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5879 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5880 file, linenum, curproxy->id);
5881 err_code |= ERR_WARN;
5882 }
5883 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005884 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5885 if (*(args[1]) == 0) {
5886 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5887 err_code |= ERR_ALERT | ERR_FATAL;
5888 goto out;
5889 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005890 chunk_destroy(&curproxy->log_tag);
5891 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005892 }
William Lallemand0f99e342011-10-12 17:50:54 +02005893 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5894 /* delete previous herited or defined syslog servers */
5895 struct logsrv *back;
5896
5897 if (*(args[1]) != 0) {
5898 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
5902
William Lallemand723b73a2012-02-08 16:37:49 +01005903 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5904 LIST_DEL(&tmplogsrv->list);
5905 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005906 }
5907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005909 struct logsrv *logsrv;
5910
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005912 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005913 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005914 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005915 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005916 LIST_INIT(&node->list);
5917 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 }
5920 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005921 struct sockaddr_storage *sk;
5922 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005923 int arg = 0;
5924 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005925
Vincent Bernat02779b62016-04-03 13:48:43 +02005926 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005927
Willy Tarreau18324f52014-06-27 18:10:07 +02005928 /* just after the address, a length may be specified */
5929 if (strcmp(args[arg+2], "len") == 0) {
5930 len = atoi(args[arg+3]);
5931 if (len < 80 || len > 65535) {
5932 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5933 file, linenum, args[arg+3]);
5934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
5936 }
5937 logsrv->maxlen = len;
5938
5939 /* skip these two args */
5940 arg += 2;
5941 }
5942 else
5943 logsrv->maxlen = MAX_SYSLOG_LEN;
5944
5945 if (logsrv->maxlen > global.max_syslog_len) {
5946 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02005947 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
5948 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
5949 logline = my_realloc2(logline, global.max_syslog_len + 1);
5950 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005951 }
5952
Dragan Dosen1322d092015-09-22 16:05:32 +02005953 /* after the length, a format may be specified */
5954 if (strcmp(args[arg+2], "format") == 0) {
5955 logsrv->format = get_log_format(args[arg+3]);
5956 if (logsrv->format < 0) {
5957 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5958 err_code |= ERR_ALERT | ERR_FATAL;
5959 goto out;
5960 }
5961
5962 /* skip these two args */
5963 arg += 2;
5964 }
5965
William Lallemanddf1425a2015-04-28 20:17:49 +02005966 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5967 goto out;
5968
Willy Tarreau18324f52014-06-27 18:10:07 +02005969 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005970 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005971 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975 }
5976
William Lallemand0f99e342011-10-12 17:50:54 +02005977 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005978 if (*(args[arg+3])) {
5979 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005980 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005981 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005982 err_code |= ERR_ALERT | ERR_FATAL;
5983 goto out;
5984
Willy Tarreaubaaee002006-06-26 02:48:02 +02005985 }
5986 }
5987
William Lallemand0f99e342011-10-12 17:50:54 +02005988 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005989 if (*(args[arg+4])) {
5990 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005991 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005992 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005996 }
5997 }
5998
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005999 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006000 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006001 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006002 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006003 goto out;
6004 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006005
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006006 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006007
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006008 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006009 if (port1 != port2) {
6010 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6011 file, linenum, args[0], args[1]);
6012 err_code |= ERR_ALERT | ERR_FATAL;
6013 goto out;
6014 }
6015
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006016 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006017 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018 }
William Lallemand0f99e342011-10-12 17:50:54 +02006019
6020 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 }
6022 else {
6023 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6024 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027 }
6028 }
6029 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006030 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006031 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006032 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006033 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006034
Willy Tarreau977b8e42006-12-29 14:19:17 +01006035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006036 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006037
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006039 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6040 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006041 err_code |= ERR_ALERT | ERR_FATAL;
6042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006044
6045 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006046 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6047 free(curproxy->conn_src.iface_name);
6048 curproxy->conn_src.iface_name = NULL;
6049 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006050
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006051 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006052 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006053 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006054 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006055 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006056 goto out;
6057 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006058
6059 proto = protocol_by_family(sk->ss_family);
6060 if (!proto || !proto->connect) {
6061 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006062 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006063 err_code |= ERR_ALERT | ERR_FATAL;
6064 goto out;
6065 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006066
6067 if (port1 != port2) {
6068 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6069 file, linenum, args[0], args[1]);
6070 err_code |= ERR_ALERT | ERR_FATAL;
6071 goto out;
6072 }
6073
Willy Tarreauef9a3602012-12-08 22:29:20 +01006074 curproxy->conn_src.source_addr = *sk;
6075 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006076
6077 cur_arg = 2;
6078 while (*(args[cur_arg])) {
6079 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006080#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006081 if (!*args[cur_arg + 1]) {
6082 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6083 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006084 err_code |= ERR_ALERT | ERR_FATAL;
6085 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006086 }
6087
6088 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006089 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6090 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006091 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006092 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6093 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006094 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6095 char *name, *end;
6096
6097 name = args[cur_arg+1] + 7;
6098 while (isspace(*name))
6099 name++;
6100
6101 end = name;
6102 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6103 end++;
6104
Willy Tarreauef9a3602012-12-08 22:29:20 +01006105 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6106 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6107 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6108 curproxy->conn_src.bind_hdr_len = end - name;
6109 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6110 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6111 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006112
6113 /* now look for an occurrence number */
6114 while (isspace(*end))
6115 end++;
6116 if (*end == ',') {
6117 end++;
6118 name = end;
6119 if (*end == '-')
6120 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006121 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006122 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006123 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006124 }
6125
Willy Tarreauef9a3602012-12-08 22:29:20 +01006126 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006127 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6128 " occurrences values smaller than %d.\n",
6129 file, linenum, MAX_HDR_HISTORY);
6130 err_code |= ERR_ALERT | ERR_FATAL;
6131 goto out;
6132 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006133 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006134 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006135
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006136 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006137 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006138 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006139 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006140 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006141 goto out;
6142 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006143
6144 proto = protocol_by_family(sk->ss_family);
6145 if (!proto || !proto->connect) {
6146 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6147 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006148 err_code |= ERR_ALERT | ERR_FATAL;
6149 goto out;
6150 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006151
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006152 if (port1 != port2) {
6153 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6154 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006155 err_code |= ERR_ALERT | ERR_FATAL;
6156 goto out;
6157 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006158 curproxy->conn_src.tproxy_addr = *sk;
6159 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006160 }
6161 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006162#else /* no TPROXY support */
6163 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006164 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006165 err_code |= ERR_ALERT | ERR_FATAL;
6166 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006167#endif
6168 cur_arg += 2;
6169 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006170 }
6171
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006172 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6173#ifdef SO_BINDTODEVICE
6174 if (!*args[cur_arg + 1]) {
6175 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6176 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006177 err_code |= ERR_ALERT | ERR_FATAL;
6178 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006179 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006180 free(curproxy->conn_src.iface_name);
6181 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6182 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006183 global.last_checks |= LSTCHK_NETADM;
6184#else
6185 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6186 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006187 err_code |= ERR_ALERT | ERR_FATAL;
6188 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006189#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006190 cur_arg += 2;
6191 continue;
6192 }
6193 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006194 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006195 err_code |= ERR_ALERT | ERR_FATAL;
6196 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006199 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6200 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6201 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006202 err_code |= ERR_ALERT | ERR_FATAL;
6203 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006204 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006206 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6208 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006209 err_code |= ERR_ALERT | ERR_FATAL;
6210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006212
6213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006214 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006215 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006218 }
6219 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006220 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006221 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006222 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006223 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225 }
6226 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006227 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006228 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006229 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006230 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 }
6233 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006234 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006235 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006236 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006237 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239 }
6240 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006241 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006242 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006243 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006244 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006247 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006248 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006249 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006250 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006251 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006252 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006254 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006255 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006256 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6257 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006258 err_code |= ERR_ALERT | ERR_FATAL;
6259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006261
6262 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006263 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006264 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006265 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 }
6268 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006269 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006270 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006271 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006272 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006274 }
6275 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006276 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006277 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006278 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006279 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006281 }
6282 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006284 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006285 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006288 }
6289 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006291 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006296 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006298 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006301 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006303 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006304 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006305
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 if (curproxy == &defproxy) {
6307 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006310 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006311 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006312 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 if (*(args[1]) == 0) {
6315 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006316 err_code |= ERR_ALERT | ERR_FATAL;
6317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006319
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006320 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006321 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6322 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6323 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006324 err_code |= ERR_ALERT | ERR_FATAL;
6325 goto out;
6326 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006327 err_code |= warnif_cond_conflicts(cond,
6328 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6329 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006330 }
6331 else if (*args[2]) {
6332 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6333 file, linenum, args[0], args[2]);
6334 err_code |= ERR_ALERT | ERR_FATAL;
6335 goto out;
6336 }
6337
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006338 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006339 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006340 wl->s = strdup(args[1]);
6341 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006342 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 }
6344 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006348 err_code |= ERR_ALERT | ERR_FATAL;
6349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006351
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006353 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006354 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 }
6358 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006360 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
6365 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006367 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006371 }
6372 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006373 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6375 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006376 err_code |= ERR_ALERT | ERR_FATAL;
6377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378 }
6379
Willy Tarreauade5ec42010-01-28 19:33:49 +01006380 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006381 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006382 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006383 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385 }
6386 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006387 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006388 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006389 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006390 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 }
6393 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006394 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006395 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006396 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006397 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 }
6400 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006401 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006402
Willy Tarreaubaaee002006-06-26 02:48:02 +02006403 if (curproxy == &defproxy) {
6404 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006405 err_code |= ERR_ALERT | ERR_FATAL;
6406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006408 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006409 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006410
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 if (*(args[1]) == 0) {
6412 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006413 err_code |= ERR_ALERT | ERR_FATAL;
6414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 }
6416
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006417 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006418 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6419 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6420 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006421 err_code |= ERR_ALERT | ERR_FATAL;
6422 goto out;
6423 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006424 err_code |= warnif_cond_conflicts(cond,
6425 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6426 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006427 }
6428 else if (*args[2]) {
6429 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6430 file, linenum, args[0], args[2]);
6431 err_code |= ERR_ALERT | ERR_FATAL;
6432 goto out;
6433 }
6434
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006435 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006436 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006437 wl->s = strdup(args[1]);
6438 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439 }
6440 else if (!strcmp(args[0], "errorloc") ||
6441 !strcmp(args[0], "errorloc302") ||
6442 !strcmp(args[0], "errorloc303")) { /* error location */
6443 int errnum, errlen;
6444 char *err;
6445
Willy Tarreau977b8e42006-12-29 14:19:17 +01006446 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006447 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006448
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006450 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", 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
6455 errnum = atol(args[1]);
6456 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006457 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6458 err = malloc(errlen);
6459 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006461 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6462 err = malloc(errlen);
6463 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006464 }
6465
Willy Tarreau0f772532006-12-23 20:51:41 +01006466 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6467 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006468 chunk_destroy(&curproxy->errmsg[rc]);
6469 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006470 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006472 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006473
6474 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006475 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6476 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 free(err);
6478 }
6479 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006480 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6481 int errnum, errlen, fd;
6482 char *err;
6483 struct stat stat;
6484
6485 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006486 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006487
6488 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006489 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006490 err_code |= ERR_ALERT | ERR_FATAL;
6491 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006492 }
6493
6494 fd = open(args[2], O_RDONLY);
6495 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6496 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6497 file, linenum, args[2], args[1]);
6498 if (fd >= 0)
6499 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006500 err_code |= ERR_ALERT | ERR_FATAL;
6501 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006502 }
6503
Willy Tarreau27a674e2009-08-17 07:23:33 +02006504 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006505 errlen = stat.st_size;
6506 } else {
6507 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006508 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006509 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006510 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006511 }
6512
6513 err = malloc(errlen); /* malloc() must succeed during parsing */
6514 errnum = read(fd, err, errlen);
6515 if (errnum != errlen) {
6516 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6517 file, linenum, args[2], args[1]);
6518 close(fd);
6519 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006520 err_code |= ERR_ALERT | ERR_FATAL;
6521 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006522 }
6523 close(fd);
6524
6525 errnum = atol(args[1]);
6526 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6527 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006528 chunk_destroy(&curproxy->errmsg[rc]);
6529 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006530 break;
6531 }
6532 }
6533
6534 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006535 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6536 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006537 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006538 free(err);
6539 }
6540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006542 struct cfg_kw_list *kwl;
6543 int index;
6544
6545 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6546 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6547 if (kwl->kw[index].section != CFG_LISTEN)
6548 continue;
6549 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6550 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006551 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006552 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006553 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006554 err_code |= ERR_ALERT | ERR_FATAL;
6555 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006556 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006557 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006558 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006559 err_code |= ERR_WARN;
6560 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006561 }
Willy Tarreau93893792009-07-23 13:19:11 +02006562 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006563 }
6564 }
6565 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006566
Willy Tarreau6daf3432008-01-22 16:44:08 +01006567 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006568 err_code |= ERR_ALERT | ERR_FATAL;
6569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 }
Willy Tarreau93893792009-07-23 13:19:11 +02006571 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006572 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006573 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006574}
6575
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006576int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006577cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6578{
6579#ifdef CONFIG_HAP_NS
6580 const char *err;
6581 const char *item = args[0];
6582
6583 if (!strcmp(item, "namespace_list")) {
6584 return 0;
6585 }
6586 else if (!strcmp(item, "namespace")) {
6587 size_t idx = 1;
6588 const char *current;
6589 while (*(current = args[idx++])) {
6590 err = invalid_char(current);
6591 if (err) {
6592 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6593 file, linenum, *err, item, current);
6594 return ERR_ALERT | ERR_FATAL;
6595 }
6596
6597 if (netns_store_lookup(current, strlen(current))) {
6598 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6599 file, linenum, current);
6600 return ERR_ALERT | ERR_FATAL;
6601 }
6602 if (!netns_store_insert(current)) {
6603 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6604 file, linenum, current);
6605 return ERR_ALERT | ERR_FATAL;
6606 }
6607 }
6608 }
6609
6610 return 0;
6611#else
6612 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6613 file, linenum);
6614 return ERR_ALERT | ERR_FATAL;
6615#endif
6616}
6617
6618int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006619cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6620{
6621
6622 int err_code = 0;
6623 const char *err;
6624
6625 if (!strcmp(args[0], "userlist")) { /* new userlist */
6626 struct userlist *newul;
6627
6628 if (!*args[1]) {
6629 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6630 file, linenum, args[0]);
6631 err_code |= ERR_ALERT | ERR_FATAL;
6632 goto out;
6633 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006634 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6635 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006636
6637 err = invalid_char(args[1]);
6638 if (err) {
6639 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6640 file, linenum, *err, args[0], args[1]);
6641 err_code |= ERR_ALERT | ERR_FATAL;
6642 goto out;
6643 }
6644
6645 for (newul = userlist; newul; newul = newul->next)
6646 if (!strcmp(newul->name, args[1])) {
6647 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6648 file, linenum, args[1]);
6649 err_code |= ERR_WARN;
6650 goto out;
6651 }
6652
Vincent Bernat02779b62016-04-03 13:48:43 +02006653 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006654 if (!newul) {
6655 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6656 err_code |= ERR_ALERT | ERR_ABORT;
6657 goto out;
6658 }
6659
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006661 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006662 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6663 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006664 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006665 goto out;
6666 }
6667
6668 newul->next = userlist;
6669 userlist = newul;
6670
6671 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006672 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006673 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006674 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006675
6676 if (!*args[1]) {
6677 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6678 file, linenum, args[0]);
6679 err_code |= ERR_ALERT | ERR_FATAL;
6680 goto out;
6681 }
6682
6683 err = invalid_char(args[1]);
6684 if (err) {
6685 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6686 file, linenum, *err, args[0], args[1]);
6687 err_code |= ERR_ALERT | ERR_FATAL;
6688 goto out;
6689 }
6690
William Lallemand4ac9f542015-05-28 18:03:51 +02006691 if (!userlist)
6692 goto out;
6693
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006694 for (ag = userlist->groups; ag; ag = ag->next)
6695 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006696 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6697 file, linenum, args[1], userlist->name);
6698 err_code |= ERR_ALERT;
6699 goto out;
6700 }
6701
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006702 ag = calloc(1, sizeof(*ag));
6703 if (!ag) {
6704 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6705 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006706 goto out;
6707 }
6708
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006709 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006710 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006711 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6712 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006713 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006714 goto out;
6715 }
6716
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006717 cur_arg = 2;
6718
6719 while (*args[cur_arg]) {
6720 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006721 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006722 cur_arg += 2;
6723 continue;
6724 } else {
6725 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6726 file, linenum, args[0]);
6727 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006728 free(ag->groupusers);
6729 free(ag->name);
6730 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006731 goto out;
6732 }
6733 }
6734
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006735 ag->next = userlist->groups;
6736 userlist->groups = ag;
6737
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006738 } else if (!strcmp(args[0], "user")) { /* new user */
6739 struct auth_users *newuser;
6740 int cur_arg;
6741
6742 if (!*args[1]) {
6743 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6744 file, linenum, args[0]);
6745 err_code |= ERR_ALERT | ERR_FATAL;
6746 goto out;
6747 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006748 if (!userlist)
6749 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006750
6751 for (newuser = userlist->users; newuser; newuser = newuser->next)
6752 if (!strcmp(newuser->user, args[1])) {
6753 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6754 file, linenum, args[1], userlist->name);
6755 err_code |= ERR_ALERT;
6756 goto out;
6757 }
6758
Vincent Bernat02779b62016-04-03 13:48:43 +02006759 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006760 if (!newuser) {
6761 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6762 err_code |= ERR_ALERT | ERR_ABORT;
6763 goto out;
6764 }
6765
6766 newuser->user = strdup(args[1]);
6767
6768 newuser->next = userlist->users;
6769 userlist->users = newuser;
6770
6771 cur_arg = 2;
6772
6773 while (*args[cur_arg]) {
6774 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006775#ifdef CONFIG_HAP_CRYPT
6776 if (!crypt("", args[cur_arg + 1])) {
6777 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6778 file, linenum, newuser->user);
6779 err_code |= ERR_ALERT | ERR_FATAL;
6780 goto out;
6781 }
6782#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006783 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6784 file, linenum);
6785 err_code |= ERR_ALERT;
6786#endif
6787 newuser->pass = strdup(args[cur_arg + 1]);
6788 cur_arg += 2;
6789 continue;
6790 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6791 newuser->pass = strdup(args[cur_arg + 1]);
6792 newuser->flags |= AU_O_INSECURE;
6793 cur_arg += 2;
6794 continue;
6795 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006796 newuser->u.groups_names = 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 'password', 'insecure-password' and 'groups' options.\n",
6801 file, linenum, args[0]);
6802 err_code |= ERR_ALERT | ERR_FATAL;
6803 goto out;
6804 }
6805 }
6806 } else {
6807 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6808 err_code |= ERR_ALERT | ERR_FATAL;
6809 }
6810
6811out:
6812 return err_code;
6813}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006814
Christopher Faulet79bdef32016-11-04 22:36:15 +01006815int
6816cfg_parse_scope(const char *file, int linenum, char *line)
6817{
6818 char *beg, *end, *scope = NULL;
6819 int err_code = 0;
6820 const char *err;
6821
6822 beg = line + 1;
6823 end = strchr(beg, ']');
6824
6825 /* Detect end of scope declaration */
6826 if (!end || end == beg) {
6827 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6828 file, linenum);
6829 err_code |= ERR_ALERT | ERR_FATAL;
6830 goto out;
6831 }
6832
6833 /* Get scope name and check its validity */
6834 scope = my_strndup(beg, end-beg);
6835 err = invalid_char(scope);
6836 if (err) {
6837 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6838 file, linenum, *err);
6839 err_code |= ERR_ALERT | ERR_ABORT;
6840 goto out;
6841 }
6842
6843 /* Be sure to have a scope declaration alone on its line */
6844 line = end+1;
6845 while (isspace((unsigned char)*line))
6846 line++;
6847 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6848 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6849 file, linenum, *line);
6850 err_code |= ERR_ALERT | ERR_ABORT;
6851 goto out;
6852 }
6853
6854 /* We have a valid scope declaration, save it */
6855 free(cfg_scope);
6856 cfg_scope = scope;
6857 scope = NULL;
6858
6859 out:
6860 free(scope);
6861 return err_code;
6862}
6863
Willy Tarreaubaaee002006-06-26 02:48:02 +02006864/*
6865 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006866 * Returns the error code, 0 if OK, or any combination of :
6867 * - ERR_ABORT: must abort ASAP
6868 * - ERR_FATAL: we can continue parsing but not start the service
6869 * - ERR_WARN: a warning has been emitted
6870 * - ERR_ALERT: an alert has been emitted
6871 * Only the two first ones can stop processing, the two others are just
6872 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006873 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006874int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006875{
William Lallemand64e84512015-05-12 14:25:37 +02006876 char *thisline;
6877 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006878 FILE *f;
6879 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006880 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006881 struct cfg_section *cs = NULL;
6882 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006883 int readbytes = 0;
6884
6885 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006886 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006887 return -1;
6888 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006889
David Carlier97880bb2016-04-08 10:35:26 +01006890 if ((f=fopen(file,"r")) == NULL) {
6891 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006892 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006894
William Lallemandb2f07452015-05-12 14:27:13 +02006895next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006896 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006897 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006898 char *end;
6899 char *args[MAX_LINE_ARGS + 1];
6900 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006901 int dquote = 0; /* double quote */
6902 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006903
Willy Tarreaubaaee002006-06-26 02:48:02 +02006904 linenum++;
6905
6906 end = line + strlen(line);
6907
William Lallemand64e84512015-05-12 14:25:37 +02006908 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006909 /* Check if we reached the limit and the last char is not \n.
6910 * Watch out for the last line without the terminating '\n'!
6911 */
William Lallemand64e84512015-05-12 14:25:37 +02006912 char *newline;
6913 int newlinesize = linesize * 2;
6914
6915 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6916 if (newline == NULL) {
6917 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6918 file, linenum);
6919 err_code |= ERR_ALERT | ERR_FATAL;
6920 continue;
6921 }
6922
6923 readbytes = linesize - 1;
6924 linesize = newlinesize;
6925 thisline = newline;
6926 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006927 }
6928
William Lallemand64e84512015-05-12 14:25:37 +02006929 readbytes = 0;
6930
Willy Tarreaubaaee002006-06-26 02:48:02 +02006931 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006932 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006933 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006934
Christopher Faulet79bdef32016-11-04 22:36:15 +01006935
6936 if (*line == '[') {/* This is the begining if a scope */
6937 err_code |= cfg_parse_scope(file, linenum, line);
6938 goto next_line;
6939 }
6940
Willy Tarreaubaaee002006-06-26 02:48:02 +02006941 arg = 0;
6942 args[arg] = line;
6943
6944 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006945 if (*line == '"' && !squote) { /* double quote outside single quotes */
6946 if (dquote)
6947 dquote = 0;
6948 else
6949 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006950 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006951 end--;
6952 }
6953 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6954 if (squote)
6955 squote = 0;
6956 else
6957 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006958 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006959 end--;
6960 }
6961 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006962 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6963 * C equivalent value. Other combinations left unchanged (eg: \1).
6964 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006965 int skip = 0;
6966 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6967 *line = line[1];
6968 skip = 1;
6969 }
6970 else if (line[1] == 'r') {
6971 *line = '\r';
6972 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006974 else if (line[1] == 'n') {
6975 *line = '\n';
6976 skip = 1;
6977 }
6978 else if (line[1] == 't') {
6979 *line = '\t';
6980 skip = 1;
6981 }
6982 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006983 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006984 unsigned char hex1, hex2;
6985 hex1 = toupper(line[2]) - '0';
6986 hex2 = toupper(line[3]) - '0';
6987 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6988 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6989 *line = (hex1<<4) + hex2;
6990 skip = 3;
6991 }
6992 else {
6993 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006994 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006996 } else if (line[1] == '"') {
6997 *line = '"';
6998 skip = 1;
6999 } else if (line[1] == '\'') {
7000 *line = '\'';
7001 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007002 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7003 *line = '$';
7004 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005 }
7006 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007007 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 end -= skip;
7009 }
7010 line++;
7011 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007012 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013 /* end of string, end of loop */
7014 *line = 0;
7015 break;
7016 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007017 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007019 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007020 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007021 line++;
7022 args[++arg] = line;
7023 }
William Lallemandb2f07452015-05-12 14:27:13 +02007024 else if (dquote && *line == '$') {
7025 /* environment variables are evaluated inside double quotes */
7026 char *var_beg;
7027 char *var_end;
7028 char save_char;
7029 char *value;
7030 int val_len;
7031 int newlinesize;
7032 int braces = 0;
7033
7034 var_beg = line + 1;
7035 var_end = var_beg;
7036
7037 if (*var_beg == '{') {
7038 var_beg++;
7039 var_end++;
7040 braces = 1;
7041 }
7042
7043 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7044 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7045 err_code |= ERR_ALERT | ERR_FATAL;
7046 goto next_line; /* skip current line */
7047 }
7048
7049 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7050 var_end++;
7051
7052 save_char = *var_end;
7053 *var_end = '\0';
7054 value = getenv(var_beg);
7055 *var_end = save_char;
7056 val_len = value ? strlen(value) : 0;
7057
7058 if (braces) {
7059 if (*var_end == '}') {
7060 var_end++;
7061 braces = 0;
7062 } else {
7063 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7064 err_code |= ERR_ALERT | ERR_FATAL;
7065 goto next_line; /* skip current line */
7066 }
7067 }
7068
7069 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7070
7071 /* if not enough space in thisline */
7072 if (newlinesize > linesize) {
7073 char *newline;
7074
7075 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7076 if (newline == NULL) {
7077 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7078 err_code |= ERR_ALERT | ERR_FATAL;
7079 goto next_line; /* slip current line */
7080 }
7081 /* recompute pointers if realloc returns a new pointer */
7082 if (newline != thisline) {
7083 int i;
7084 int diff;
7085
7086 for (i = 0; i <= arg; i++) {
7087 diff = args[i] - thisline;
7088 args[i] = newline + diff;
7089 }
7090
7091 diff = var_end - thisline;
7092 var_end = newline + diff;
7093 diff = end - thisline;
7094 end = newline + diff;
7095 diff = line - thisline;
7096 line = newline + diff;
7097 thisline = newline;
7098 }
7099 linesize = newlinesize;
7100 }
7101
7102 /* insert value inside the line */
7103 memmove(line + val_len, var_end, end - var_end + 1);
7104 memcpy(line, value, val_len);
7105 end += val_len - (var_end - line);
7106 line += val_len;
7107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007108 else {
7109 line++;
7110 }
7111 }
William Lallemandb2f07452015-05-12 14:27:13 +02007112
William Lallemandf9873ba2015-05-05 17:37:14 +02007113 if (dquote) {
7114 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7115 err_code |= ERR_ALERT | ERR_FATAL;
7116 }
7117
7118 if (squote) {
7119 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7120 err_code |= ERR_ALERT | ERR_FATAL;
7121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007122
7123 /* empty line */
7124 if (!**args)
7125 continue;
7126
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007127 if (*line) {
7128 /* we had to stop due to too many args.
7129 * Let's terminate the string, print the offending part then cut the
7130 * last arg.
7131 */
7132 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7133 line++;
7134 *line = '\0';
7135
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007136 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007137 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007138 err_code |= ERR_ALERT | ERR_FATAL;
7139 args[arg] = line;
7140 }
7141
Willy Tarreau540abe42007-05-02 20:50:16 +02007142 /* zero out remaining args and ensure that at least one entry
7143 * is zeroed out.
7144 */
7145 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007146 args[arg] = line;
7147 }
7148
Willy Tarreau3842f002009-06-14 11:39:52 +02007149 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007150 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007151 char *tmp;
7152
Willy Tarreau3842f002009-06-14 11:39:52 +02007153 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007154 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007155 for (arg=0; *args[arg+1]; arg++)
7156 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007157 *tmp = '\0'; // fix the next arg to \0
7158 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007159 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007160 else if (!strcmp(args[0], "default")) {
7161 kwm = KWM_DEF;
7162 for (arg=0; *args[arg+1]; arg++)
7163 args[arg] = args[arg+1]; // shift args after inversion
7164 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007165
William Lallemand0f99e342011-10-12 17:50:54 +02007166 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7167 strcmp(args[0], "log") != 0) {
7168 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007169 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007170 }
7171
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007172 /* detect section start */
7173 list_for_each_entry(ics, &sections, list) {
7174 if (strcmp(args[0], ics->section_name) == 0) {
7175 cursection = ics->section_name;
7176 cs = ics;
7177 break;
7178 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007179 }
7180
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007182 if (cs)
7183 err_code |= cs->section_parser(file, linenum, args, kwm);
7184 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007185 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007186 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007187 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007188
7189 if (err_code & ERR_ABORT)
7190 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007191 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007192 free(cfg_scope);
7193 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007194 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007195 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007196 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007197 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007198}
7199
Willy Tarreau64ab6072014-09-16 12:17:36 +02007200/* This function propagates processes from frontend <from> to backend <to> so
7201 * that it is always guaranteed that a backend pointed to by a frontend is
7202 * bound to all of its processes. After that, if the target is a "listen"
7203 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007204 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007205 * checked first to ensure that <to> is already bound to all processes of
7206 * <from>, there is no risk of looping and we ensure to follow the shortest
7207 * path to the destination.
7208 *
7209 * It is possible to set <to> to NULL for the first call so that the function
7210 * takes care of visiting the initial frontend in <from>.
7211 *
7212 * It is important to note that the function relies on the fact that all names
7213 * have already been resolved.
7214 */
7215void propagate_processes(struct proxy *from, struct proxy *to)
7216{
7217 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007218
7219 if (to) {
7220 /* check whether we need to go down */
7221 if (from->bind_proc &&
7222 (from->bind_proc & to->bind_proc) == from->bind_proc)
7223 return;
7224
7225 if (!from->bind_proc && !to->bind_proc)
7226 return;
7227
7228 to->bind_proc = from->bind_proc ?
7229 (to->bind_proc | from->bind_proc) : 0;
7230
7231 /* now propagate down */
7232 from = to;
7233 }
7234
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007235 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007236 return;
7237
Willy Tarreauf6b70012014-12-18 14:00:43 +01007238 if (from->state == PR_STSTOPPED)
7239 return;
7240
Willy Tarreau64ab6072014-09-16 12:17:36 +02007241 /* default_backend */
7242 if (from->defbe.be)
7243 propagate_processes(from, from->defbe.be);
7244
7245 /* use_backend */
7246 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007247 if (rule->dynamic)
7248 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007249 to = rule->be.backend;
7250 propagate_processes(from, to);
7251 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007252}
7253
Willy Tarreaubb925012009-07-23 13:36:36 +02007254/*
7255 * Returns the error code, 0 if OK, or any combination of :
7256 * - ERR_ABORT: must abort ASAP
7257 * - ERR_FATAL: we can continue parsing but not start the service
7258 * - ERR_WARN: a warning has been emitted
7259 * - ERR_ALERT: an alert has been emitted
7260 * Only the two first ones can stop processing, the two others are just
7261 * indicators.
7262 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007263int check_config_validity()
7264{
7265 int cfgerr = 0;
7266 struct proxy *curproxy = NULL;
7267 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007268 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007269 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007270 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007271 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007272
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007273 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007274 /*
7275 * Now, check for the integrity of all that we have collected.
7276 */
7277
7278 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007279 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007280
Willy Tarreau193b8c62012-11-22 00:17:38 +01007281 if (!global.tune.max_http_hdr)
7282 global.tune.max_http_hdr = MAX_HTTP_HDR;
7283
7284 if (!global.tune.cookie_len)
7285 global.tune.cookie_len = CAPTURE_LEN;
7286
7287 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7288
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007289 /* Post initialisation of the users and groups lists. */
7290 err_code = userlist_postinit();
7291 if (err_code != ERR_NONE)
7292 goto out;
7293
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007294 /* first, we will invert the proxy list order */
7295 curproxy = NULL;
7296 while (proxy) {
7297 struct proxy *next;
7298
7299 next = proxy->next;
7300 proxy->next = curproxy;
7301 curproxy = proxy;
7302 if (!next)
7303 break;
7304 proxy = next;
7305 }
7306
Willy Tarreau419ead82014-09-16 13:41:21 +02007307 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007308 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007309 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007310 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007311 struct act_rule *trule;
7312 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007313 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007314 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007315 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007316
Willy Tarreau050536d2012-10-04 08:47:34 +02007317 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007318 /* proxy ID not set, use automatic numbering with first
7319 * spare entry starting with next_pxid.
7320 */
7321 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7322 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7323 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007324 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007325 next_pxid++;
7326
Willy Tarreau55ea7572007-06-17 19:56:27 +02007327
Willy Tarreaubaaee002006-06-26 02:48:02 +02007328 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007329 /* ensure we don't keep listeners uselessly bound */
7330 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007331 free((void *)curproxy->table.peers.name);
7332 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007333 continue;
7334 }
7335
Willy Tarreau102df612014-05-07 23:56:38 +02007336 /* Check multi-process mode compatibility for the current proxy */
7337
7338 if (curproxy->bind_proc) {
7339 /* an explicit bind-process was specified, let's check how many
7340 * processes remain.
7341 */
David Carliere6c39412015-07-02 07:00:17 +00007342 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007343
7344 curproxy->bind_proc &= nbits(global.nbproc);
7345 if (!curproxy->bind_proc && nbproc == 1) {
7346 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);
7347 curproxy->bind_proc = 1;
7348 }
7349 else if (!curproxy->bind_proc && nbproc > 1) {
7350 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);
7351 curproxy->bind_proc = 0;
7352 }
7353 }
7354
Willy Tarreau3d209582014-05-09 17:06:11 +02007355 /* check and reduce the bind-proc of each listener */
7356 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7357 unsigned long mask;
7358
7359 if (!bind_conf->bind_proc)
7360 continue;
7361
7362 mask = nbits(global.nbproc);
7363 if (curproxy->bind_proc)
7364 mask &= curproxy->bind_proc;
7365 /* mask cannot be null here thanks to the previous checks */
7366
David Carliere6c39412015-07-02 07:00:17 +00007367 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007368 bind_conf->bind_proc &= mask;
7369
7370 if (!bind_conf->bind_proc && nbproc == 1) {
7371 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",
7372 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7373 bind_conf->bind_proc = mask & ~(mask - 1);
7374 }
7375 else if (!bind_conf->bind_proc && nbproc > 1) {
7376 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",
7377 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7378 bind_conf->bind_proc = 0;
7379 }
7380 }
7381
Willy Tarreauff01a212009-03-15 13:46:16 +01007382 switch (curproxy->mode) {
7383 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007384 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007385 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007386 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7387 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007388 cfgerr++;
7389 }
7390
7391 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007392 Warning("config : servers will be ignored for %s '%s'.\n",
7393 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007394 break;
7395
7396 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007397 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007398 break;
7399
7400 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007401 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007402 break;
7403 }
7404
Willy Tarreauf3934b82015-08-11 11:36:45 +02007405 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7406 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7407 proxy_type_str(curproxy), curproxy->id);
7408 err_code |= ERR_WARN;
7409 }
7410
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007411 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007412 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007413 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007414 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7415 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007416 cfgerr++;
7417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007418#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007419 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007420 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7421 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007422 cfgerr++;
7423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007424#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007425 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007426 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7427 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007428 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007429 }
7430 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007431 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007432 /* If no LB algo is set in a backend, and we're not in
7433 * transparent mode, dispatch mode nor proxy mode, we
7434 * want to use balance roundrobin by default.
7435 */
7436 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7437 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007438 }
7439 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007440
Willy Tarreau1620ec32011-08-06 17:05:02 +02007441 if (curproxy->options & PR_O_DISPATCH)
7442 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7443 else if (curproxy->options & PR_O_HTTP_PROXY)
7444 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7445 else if (curproxy->options & PR_O_TRANSP)
7446 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007447
Willy Tarreau1620ec32011-08-06 17:05:02 +02007448 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7449 if (curproxy->options & PR_O_DISABLE404) {
7450 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7451 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7452 err_code |= ERR_WARN;
7453 curproxy->options &= ~PR_O_DISABLE404;
7454 }
7455 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7456 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7457 "send-state", proxy_type_str(curproxy), curproxy->id);
7458 err_code |= ERR_WARN;
7459 curproxy->options &= ~PR_O2_CHK_SNDST;
7460 }
Willy Tarreauef781042010-01-27 11:53:01 +01007461 }
7462
Simon Horman98637e52014-06-20 12:30:16 +09007463 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7464 if (!global.external_check) {
7465 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7466 curproxy->id, "option external-check");
7467 cfgerr++;
7468 }
7469 if (!curproxy->check_command) {
7470 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7471 curproxy->id, "option external-check");
7472 cfgerr++;
7473 }
7474 }
7475
Simon Horman64e34162015-02-06 11:11:57 +09007476 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007477 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7478 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007479 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7480 "'email-alert myhostname', or 'email-alert to' "
7481 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007482 "to be present).\n",
7483 proxy_type_str(curproxy), curproxy->id);
7484 err_code |= ERR_WARN;
7485 free_email_alert(curproxy);
7486 }
7487 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007488 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007489 }
7490
Simon Horman98637e52014-06-20 12:30:16 +09007491 if (curproxy->check_command) {
7492 int clear = 0;
7493 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7494 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7495 "external-check command", proxy_type_str(curproxy), curproxy->id);
7496 err_code |= ERR_WARN;
7497 clear = 1;
7498 }
7499 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007500 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007501 curproxy->id, "external-check command");
7502 cfgerr++;
7503 }
7504 if (clear) {
7505 free(curproxy->check_command);
7506 curproxy->check_command = NULL;
7507 }
7508 }
7509
7510 if (curproxy->check_path) {
7511 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7512 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7513 "external-check path", proxy_type_str(curproxy), curproxy->id);
7514 err_code |= ERR_WARN;
7515 free(curproxy->check_path);
7516 curproxy->check_path = NULL;
7517 }
7518 }
7519
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007520 /* if a default backend was specified, let's find it */
7521 if (curproxy->defbe.name) {
7522 struct proxy *target;
7523
Willy Tarreauafb39922015-05-26 12:04:09 +02007524 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007525 if (!target) {
7526 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7527 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007528 cfgerr++;
7529 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007530 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7531 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007532 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007533 } else if (target->mode != curproxy->mode &&
7534 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7535
7536 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7537 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7538 curproxy->conf.file, curproxy->conf.line,
7539 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7540 target->conf.file, target->conf.line);
7541 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007542 } else {
7543 free(curproxy->defbe.name);
7544 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007545 /* Update tot_fe_maxconn for a further fullconn's computation */
7546 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007547 /* Emit a warning if this proxy also has some servers */
7548 if (curproxy->srv) {
7549 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7550 curproxy->id);
7551 err_code |= ERR_WARN;
7552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007553 }
7554 }
7555
Emeric Brun3f783572017-01-12 11:21:28 +01007556 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7557 /* Case of listen without default backend
7558 * The curproxy will be its own default backend
7559 * so we update tot_fe_maxconn for a further
7560 * fullconn's computation */
7561 curproxy->tot_fe_maxconn += curproxy->maxconn;
7562 }
7563
Willy Tarreau55ea7572007-06-17 19:56:27 +02007564 /* find the target proxy for 'use_backend' rules */
7565 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007566 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007567 struct logformat_node *node;
7568 char *pxname;
7569
7570 /* Try to parse the string as a log format expression. If the result
7571 * of the parsing is only one entry containing a simple string, then
7572 * it's a standard string corresponding to a static rule, thus the
7573 * parsing is cancelled and be.name is restored to be resolved.
7574 */
7575 pxname = rule->be.name;
7576 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007577 curproxy->conf.args.ctx = ARGC_UBK;
7578 curproxy->conf.args.file = rule->file;
7579 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007580 err = NULL;
7581 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7582 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7583 rule->file, rule->line, pxname, err);
7584 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007585 cfgerr++;
7586 continue;
7587 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007588 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7589
7590 if (!LIST_ISEMPTY(&rule->be.expr)) {
7591 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7592 rule->dynamic = 1;
7593 free(pxname);
7594 continue;
7595 }
7596 /* simple string: free the expression and fall back to static rule */
7597 free(node->arg);
7598 free(node);
7599 }
7600
7601 rule->dynamic = 0;
7602 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007603
Willy Tarreauafb39922015-05-26 12:04:09 +02007604 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007605 if (!target) {
7606 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7607 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007608 cfgerr++;
7609 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007610 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7611 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007612 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007613 } else if (target->mode != curproxy->mode &&
7614 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7615
7616 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7617 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7618 curproxy->conf.file, curproxy->conf.line,
7619 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7620 target->conf.file, target->conf.line);
7621 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007622 } else {
7623 free((void *)rule->be.name);
7624 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007625 /* For each target of switching rules, we update
7626 * their tot_fe_maxconn, except if a previous rule point
7627 * on the same backend or on the default backend */
7628 if (rule->be.backend != curproxy->defbe.be) {
7629 struct switching_rule *swrule;
7630
7631 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7632 if (rule == swrule) {
7633 target->tot_fe_maxconn += curproxy->maxconn;
7634 break;
7635 }
7636 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7637 /* there is multiple ref of this backend */
7638 break;
7639 }
7640 }
7641 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007642 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007643 }
7644
Willy Tarreau64ab6072014-09-16 12:17:36 +02007645 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007646 list_for_each_entry(srule, &curproxy->server_rules, list) {
7647 struct server *target = findserver(curproxy, srule->srv.name);
7648
7649 if (!target) {
7650 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7651 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7652 cfgerr++;
7653 continue;
7654 }
7655 free((void *)srule->srv.name);
7656 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007657 }
7658
Emeric Brunb982a3d2010-01-04 15:45:53 +01007659 /* find the target table for 'stick' rules */
7660 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7661 struct proxy *target;
7662
Emeric Brun1d33b292010-01-04 15:47:17 +01007663 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7664 if (mrule->flags & STK_IS_STORE)
7665 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7666
Emeric Brunb982a3d2010-01-04 15:45:53 +01007667 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007668 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007669 else
7670 target = curproxy;
7671
7672 if (!target) {
7673 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7674 curproxy->id, mrule->table.name);
7675 cfgerr++;
7676 }
7677 else if (target->table.size == 0) {
7678 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7679 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7680 cfgerr++;
7681 }
Willy Tarreau12785782012-04-27 21:37:17 +02007682 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7683 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007684 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7685 cfgerr++;
7686 }
7687 else {
7688 free((void *)mrule->table.name);
7689 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007690 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007691 }
7692 }
7693
7694 /* find the target table for 'store response' rules */
7695 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7696 struct proxy *target;
7697
Emeric Brun1d33b292010-01-04 15:47:17 +01007698 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7699
Emeric Brunb982a3d2010-01-04 15:45:53 +01007700 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007701 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007702 else
7703 target = curproxy;
7704
7705 if (!target) {
7706 Alert("Proxy '%s': unable to find store table '%s'.\n",
7707 curproxy->id, mrule->table.name);
7708 cfgerr++;
7709 }
7710 else if (target->table.size == 0) {
7711 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7712 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7713 cfgerr++;
7714 }
Willy Tarreau12785782012-04-27 21:37:17 +02007715 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7716 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007717 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7718 cfgerr++;
7719 }
7720 else {
7721 free((void *)mrule->table.name);
7722 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007723 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007724 }
7725 }
7726
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007727 /* find the target table for 'tcp-request' layer 4 rules */
7728 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7729 struct proxy *target;
7730
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007731 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007732 continue;
7733
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007734 if (trule->arg.trk_ctr.table.n)
7735 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007736 else
7737 target = curproxy;
7738
7739 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007740 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007741 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007742 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007743 cfgerr++;
7744 }
7745 else if (target->table.size == 0) {
7746 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007747 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007748 cfgerr++;
7749 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007750 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007751 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007752 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007753 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007754 cfgerr++;
7755 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007756 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007757 free(trule->arg.trk_ctr.table.n);
7758 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007759 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007760 * to pass a list of counters to track and allocate them right here using
7761 * stktable_alloc_data_type().
7762 */
7763 }
7764 }
7765
Willy Tarreau620408f2016-10-21 16:37:51 +02007766 /* find the target table for 'tcp-request' layer 5 rules */
7767 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7768 struct proxy *target;
7769
7770 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7771 continue;
7772
7773 if (trule->arg.trk_ctr.table.n)
7774 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7775 else
7776 target = curproxy;
7777
7778 if (!target) {
7779 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7780 curproxy->id, trule->arg.trk_ctr.table.n,
7781 tcp_trk_idx(trule->action));
7782 cfgerr++;
7783 }
7784 else if (target->table.size == 0) {
7785 Alert("Proxy '%s': table '%s' used but not configured.\n",
7786 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7787 cfgerr++;
7788 }
7789 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7790 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7791 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7792 tcp_trk_idx(trule->action));
7793 cfgerr++;
7794 }
7795 else {
7796 free(trule->arg.trk_ctr.table.n);
7797 trule->arg.trk_ctr.table.t = &target->table;
7798 /* Note: if we decide to enhance the track-sc syntax, we may be able
7799 * to pass a list of counters to track and allocate them right here using
7800 * stktable_alloc_data_type().
7801 */
7802 }
7803 }
7804
Willy Tarreaud1f96522010-08-03 19:34:32 +02007805 /* find the target table for 'tcp-request' layer 6 rules */
7806 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7807 struct proxy *target;
7808
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007809 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007810 continue;
7811
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007812 if (trule->arg.trk_ctr.table.n)
7813 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007814 else
7815 target = curproxy;
7816
7817 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007818 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007819 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007820 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007821 cfgerr++;
7822 }
7823 else if (target->table.size == 0) {
7824 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007825 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007826 cfgerr++;
7827 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007828 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007829 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007830 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007831 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007832 cfgerr++;
7833 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007834 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007835 free(trule->arg.trk_ctr.table.n);
7836 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007837 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007838 * to pass a list of counters to track and allocate them right here using
7839 * stktable_alloc_data_type().
7840 */
7841 }
7842 }
7843
Baptiste Assmanne9544932015-11-03 23:31:35 +01007844 /* parse http-request capture rules to ensure id really exists */
7845 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7846 if (hrqrule->action != ACT_CUSTOM ||
7847 hrqrule->action_ptr != http_action_req_capture_by_id)
7848 continue;
7849
7850 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7851 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7852 curproxy->id, hrqrule->arg.capid.idx);
7853 cfgerr++;
7854 }
7855 }
7856
7857 /* parse http-response capture rules to ensure id really exists */
7858 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7859 if (hrqrule->action != ACT_CUSTOM ||
7860 hrqrule->action_ptr != http_action_res_capture_by_id)
7861 continue;
7862
7863 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7864 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7865 curproxy->id, hrqrule->arg.capid.idx);
7866 cfgerr++;
7867 }
7868 }
7869
Willy Tarreau09448f72014-06-25 18:12:15 +02007870 /* find the target table for 'http-request' layer 7 rules */
7871 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7872 struct proxy *target;
7873
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007874 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007875 continue;
7876
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007877 if (hrqrule->arg.trk_ctr.table.n)
7878 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007879 else
7880 target = curproxy;
7881
7882 if (!target) {
7883 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007884 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007885 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007886 cfgerr++;
7887 }
7888 else if (target->table.size == 0) {
7889 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007890 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007891 cfgerr++;
7892 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007893 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007894 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007895 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007896 http_trk_idx(hrqrule->action));
7897 cfgerr++;
7898 }
7899 else {
7900 free(hrqrule->arg.trk_ctr.table.n);
7901 hrqrule->arg.trk_ctr.table.t = &target->table;
7902 /* Note: if we decide to enhance the track-sc syntax, we may be able
7903 * to pass a list of counters to track and allocate them right here using
7904 * stktable_alloc_data_type().
7905 */
7906 }
7907 }
7908
7909 /* find the target table for 'http-response' layer 7 rules */
7910 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7911 struct proxy *target;
7912
7913 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7914 continue;
7915
7916 if (hrqrule->arg.trk_ctr.table.n)
7917 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7918 else
7919 target = curproxy;
7920
7921 if (!target) {
7922 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7923 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7924 http_trk_idx(hrqrule->action));
7925 cfgerr++;
7926 }
7927 else if (target->table.size == 0) {
7928 Alert("Proxy '%s': table '%s' used but not configured.\n",
7929 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
7930 cfgerr++;
7931 }
7932 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
7933 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7934 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
7935 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007936 cfgerr++;
7937 }
7938 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007939 free(hrqrule->arg.trk_ctr.table.n);
7940 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007941 /* Note: if we decide to enhance the track-sc syntax, we may be able
7942 * to pass a list of counters to track and allocate them right here using
7943 * stktable_alloc_data_type().
7944 */
7945 }
7946 }
7947
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007948 /* move any "block" rules at the beginning of the http-request rules */
7949 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7950 /* insert block_rules into http_req_rules at the beginning */
7951 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7952 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7953 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7954 curproxy->http_req_rules.n = curproxy->block_rules.n;
7955 LIST_INIT(&curproxy->block_rules);
7956 }
7957
Emeric Brun32da3c42010-09-23 18:39:19 +02007958 if (curproxy->table.peers.name) {
7959 struct peers *curpeers = peers;
7960
7961 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7962 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7963 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007964 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007965 break;
7966 }
7967 }
7968
7969 if (!curpeers) {
7970 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7971 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007972 free((void *)curproxy->table.peers.name);
7973 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007974 cfgerr++;
7975 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007976 else if (curpeers->state == PR_STSTOPPED) {
7977 /* silently disable this peers section */
7978 curproxy->table.peers.p = NULL;
7979 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007980 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007981 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7982 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007983 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007984 cfgerr++;
7985 }
7986 }
7987
Simon Horman9dc49962015-01-30 11:22:59 +09007988
7989 if (curproxy->email_alert.mailers.name) {
7990 struct mailers *curmailers = mailers;
7991
7992 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7993 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7994 free(curproxy->email_alert.mailers.name);
7995 curproxy->email_alert.mailers.m = curmailers;
7996 curmailers->users++;
7997 break;
7998 }
7999 }
8000
8001 if (!curmailers) {
8002 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8003 curproxy->id, curproxy->email_alert.mailers.name);
8004 free_email_alert(curproxy);
8005 cfgerr++;
8006 }
8007 }
8008
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008009 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008010 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008011 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8012 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8013 "proxy", curproxy->id);
8014 cfgerr++;
8015 goto out_uri_auth_compat;
8016 }
8017
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008018 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008019 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008020 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008021 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008022
Willy Tarreau95fa4692010-02-01 13:05:50 +01008023 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8024 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008025
8026 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008027 uri_auth_compat_req[i++] = "realm";
8028 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8029 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008030
Willy Tarreau95fa4692010-02-01 13:05:50 +01008031 uri_auth_compat_req[i++] = "unless";
8032 uri_auth_compat_req[i++] = "{";
8033 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8034 uri_auth_compat_req[i++] = "}";
8035 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008036
Willy Tarreauff011f22011-01-06 17:51:27 +01008037 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8038 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008039 cfgerr++;
8040 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008041 }
8042
Willy Tarreauff011f22011-01-06 17:51:27 +01008043 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008044
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008045 if (curproxy->uri_auth->auth_realm) {
8046 free(curproxy->uri_auth->auth_realm);
8047 curproxy->uri_auth->auth_realm = NULL;
8048 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008049
8050 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008051 }
8052out_uri_auth_compat:
8053
Dragan Dosen43885c72015-10-01 13:18:13 +02008054 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008055 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008056 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8057 if (!curproxy->conf.logformat_sd_string) {
8058 /* set the default logformat_sd_string */
8059 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8060 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008061 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008062 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008063 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008064
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008065 /* compile the log format */
8066 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008067 if (curproxy->conf.logformat_string != default_http_log_format &&
8068 curproxy->conf.logformat_string != default_tcp_log_format &&
8069 curproxy->conf.logformat_string != clf_http_log_format)
8070 free(curproxy->conf.logformat_string);
8071 curproxy->conf.logformat_string = NULL;
8072 free(curproxy->conf.lfs_file);
8073 curproxy->conf.lfs_file = NULL;
8074 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008075
8076 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8077 free(curproxy->conf.logformat_sd_string);
8078 curproxy->conf.logformat_sd_string = NULL;
8079 free(curproxy->conf.lfsd_file);
8080 curproxy->conf.lfsd_file = NULL;
8081 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008082 }
8083
Willy Tarreau62a61232013-04-12 18:13:46 +02008084 if (curproxy->conf.logformat_string) {
8085 curproxy->conf.args.ctx = ARGC_LOG;
8086 curproxy->conf.args.file = curproxy->conf.lfs_file;
8087 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008088 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008089 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008090 SMP_VAL_FE_LOG_END, &err)) {
8091 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8092 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8093 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008094 cfgerr++;
8095 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008096 curproxy->conf.args.file = NULL;
8097 curproxy->conf.args.line = 0;
8098 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008099
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008100 if (curproxy->conf.logformat_sd_string) {
8101 curproxy->conf.args.ctx = ARGC_LOGSD;
8102 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8103 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008104 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008105 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 +01008106 SMP_VAL_FE_LOG_END, &err)) {
8107 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8108 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8109 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008110 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008111 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8112 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8113 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8114 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008115 cfgerr++;
8116 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008117 curproxy->conf.args.file = NULL;
8118 curproxy->conf.args.line = 0;
8119 }
8120
Willy Tarreau62a61232013-04-12 18:13:46 +02008121 if (curproxy->conf.uniqueid_format_string) {
8122 curproxy->conf.args.ctx = ARGC_UIF;
8123 curproxy->conf.args.file = curproxy->conf.uif_file;
8124 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008125 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008126 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 +01008127 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8128 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8129 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8130 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008131 cfgerr++;
8132 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008133 curproxy->conf.args.file = NULL;
8134 curproxy->conf.args.line = 0;
8135 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008136
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008137 /* only now we can check if some args remain unresolved.
8138 * This must be done after the users and groups resolution.
8139 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008140 cfgerr += smp_resolve_args(curproxy);
8141 if (!cfgerr)
8142 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008143
Willy Tarreau2738a142006-07-08 17:28:09 +02008144 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008145 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008146 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008147 (!curproxy->timeout.connect ||
8148 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008149 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008150 " | While not properly invalid, you will certainly encounter various problems\n"
8151 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008152 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008153 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008154 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008155 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008156
Willy Tarreau1fa31262007-12-03 00:36:16 +01008157 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8158 * We must still support older configurations, so let's find out whether those
8159 * parameters have been set or must be copied from contimeouts.
8160 */
8161 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008162 if (!curproxy->timeout.tarpit ||
8163 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008164 /* tarpit timeout not set. We search in the following order:
8165 * default.tarpit, curr.connect, default.connect.
8166 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008167 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008168 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008169 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008170 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008171 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008172 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008173 }
8174 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008175 (!curproxy->timeout.queue ||
8176 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008177 /* queue timeout not set. We search in the following order:
8178 * default.queue, curr.connect, default.connect.
8179 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008180 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008181 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008182 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008183 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008184 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008185 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008186 }
8187 }
8188
Willy Tarreau1620ec32011-08-06 17:05:02 +02008189 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008190 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008191 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008192 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008193 }
8194
Willy Tarreau215663d2014-06-13 18:30:23 +02008195 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8196 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8197 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8198 proxy_type_str(curproxy), curproxy->id);
8199 err_code |= ERR_WARN;
8200 }
8201
Willy Tarreau193b8c62012-11-22 00:17:38 +01008202 /* ensure that cookie capture length is not too large */
8203 if (curproxy->capture_len >= global.tune.cookie_len) {
8204 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8205 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8206 err_code |= ERR_WARN;
8207 curproxy->capture_len = global.tune.cookie_len - 1;
8208 }
8209
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008210 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008211 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008212 curproxy->req_cap_pool = create_pool("ptrcap",
8213 curproxy->nb_req_cap * sizeof(char *),
8214 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008215 }
8216
8217 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008218 curproxy->rsp_cap_pool = create_pool("ptrcap",
8219 curproxy->nb_rsp_cap * sizeof(char *),
8220 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008221 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008222
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008223 switch (curproxy->load_server_state_from_file) {
8224 case PR_SRV_STATE_FILE_UNSPEC:
8225 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8226 break;
8227 case PR_SRV_STATE_FILE_GLOBAL:
8228 if (!global.server_state_file) {
8229 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",
8230 curproxy->id);
8231 err_code |= ERR_WARN;
8232 }
8233 break;
8234 }
8235
Willy Tarreaubaaee002006-06-26 02:48:02 +02008236 /* first, we will invert the servers list order */
8237 newsrv = NULL;
8238 while (curproxy->srv) {
8239 struct server *next;
8240
8241 next = curproxy->srv->next;
8242 curproxy->srv->next = newsrv;
8243 newsrv = curproxy->srv;
8244 if (!next)
8245 break;
8246 curproxy->srv = next;
8247 }
8248
Willy Tarreau17edc812014-01-03 12:14:34 +01008249 /* Check that no server name conflicts. This causes trouble in the stats.
8250 * We only emit a warning for the first conflict affecting each server,
8251 * in order to avoid combinatory explosion if all servers have the same
8252 * name. We do that only for servers which do not have an explicit ID,
8253 * because these IDs were made also for distinguishing them and we don't
8254 * want to annoy people who correctly manage them.
8255 */
8256 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8257 struct server *other_srv;
8258
8259 if (newsrv->puid)
8260 continue;
8261
8262 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8263 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8264 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8265 newsrv->conf.file, newsrv->conf.line,
8266 proxy_type_str(curproxy), curproxy->id,
8267 newsrv->id, other_srv->conf.line);
8268 break;
8269 }
8270 }
8271 }
8272
Willy Tarreaudd701652010-05-25 23:03:02 +02008273 /* assign automatic UIDs to servers which don't have one yet */
8274 next_id = 1;
8275 newsrv = curproxy->srv;
8276 while (newsrv != NULL) {
8277 if (!newsrv->puid) {
8278 /* server ID not set, use automatic numbering with first
8279 * spare entry starting with next_svid.
8280 */
8281 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8282 newsrv->conf.id.key = newsrv->puid = next_id;
8283 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8284 }
8285 next_id++;
8286 newsrv = newsrv->next;
8287 }
8288
Willy Tarreau20697042007-11-15 23:26:18 +01008289 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008290 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008291
Willy Tarreau62c3be22012-01-20 13:12:32 +01008292 /*
8293 * If this server supports a maxconn parameter, it needs a dedicated
8294 * tasks to fill the emptied slots when a connection leaves.
8295 * Also, resolve deferred tracking dependency if needed.
8296 */
8297 newsrv = curproxy->srv;
8298 while (newsrv != NULL) {
8299 if (newsrv->minconn > newsrv->maxconn) {
8300 /* Only 'minconn' was specified, or it was higher than or equal
8301 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8302 * this will avoid further useless expensive computations.
8303 */
8304 newsrv->maxconn = newsrv->minconn;
8305 } else if (newsrv->maxconn && !newsrv->minconn) {
8306 /* minconn was not specified, so we set it to maxconn */
8307 newsrv->minconn = newsrv->maxconn;
8308 }
8309
Willy Tarreau17d45382016-12-22 21:16:08 +01008310 /* this will also properly set the transport layer for prod and checks */
8311 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8312 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8313 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8314 }
Emeric Brun94324a42012-10-11 14:00:19 +02008315
Willy Tarreau2f075e92013-12-03 11:11:34 +01008316 /* set the check type on the server */
8317 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8318
Willy Tarreau62c3be22012-01-20 13:12:32 +01008319 if (newsrv->trackit) {
8320 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008321 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008322 char *pname, *sname;
8323
8324 pname = newsrv->trackit;
8325 sname = strrchr(pname, '/');
8326
8327 if (sname)
8328 *sname++ = '\0';
8329 else {
8330 sname = pname;
8331 pname = NULL;
8332 }
8333
8334 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008335 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008336 if (!px) {
8337 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8338 proxy_type_str(curproxy), curproxy->id,
8339 newsrv->id, pname);
8340 cfgerr++;
8341 goto next_srv;
8342 }
8343 } else
8344 px = curproxy;
8345
8346 srv = findserver(px, sname);
8347 if (!srv) {
8348 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8349 proxy_type_str(curproxy), curproxy->id,
8350 newsrv->id, sname);
8351 cfgerr++;
8352 goto next_srv;
8353 }
8354
Willy Tarreau32091232014-05-16 13:52:00 +02008355 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8356 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8357 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008358 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008359 "tracking as it does not have any check nor agent enabled.\n",
8360 proxy_type_str(curproxy), curproxy->id,
8361 newsrv->id, px->id, srv->id);
8362 cfgerr++;
8363 goto next_srv;
8364 }
8365
8366 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8367
8368 if (loop) {
8369 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8370 "belongs to a tracking chain looping back to %s/%s.\n",
8371 proxy_type_str(curproxy), curproxy->id,
8372 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008373 cfgerr++;
8374 goto next_srv;
8375 }
8376
8377 if (curproxy != px &&
8378 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8379 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8380 "tracking: disable-on-404 option inconsistency.\n",
8381 proxy_type_str(curproxy), curproxy->id,
8382 newsrv->id, px->id, srv->id);
8383 cfgerr++;
8384 goto next_srv;
8385 }
8386
Willy Tarreau62c3be22012-01-20 13:12:32 +01008387 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008388 newsrv->tracknext = srv->trackers;
8389 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008390
8391 free(newsrv->trackit);
8392 newsrv->trackit = NULL;
8393 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008394
8395 /*
8396 * resolve server's resolvers name and update the resolvers pointer
8397 * accordingly
8398 */
8399 if (newsrv->resolvers_id) {
8400 struct dns_resolvers *curr_resolvers;
8401 int found;
8402
8403 found = 0;
8404 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8405 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8406 found = 1;
8407 break;
8408 }
8409 }
8410
8411 if (!found) {
8412 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8413 proxy_type_str(curproxy), curproxy->id,
8414 newsrv->id, newsrv->resolvers_id);
8415 cfgerr++;
8416 } else {
8417 free(newsrv->resolvers_id);
8418 newsrv->resolvers_id = NULL;
8419 if (newsrv->resolution)
8420 newsrv->resolution->resolvers = curr_resolvers;
8421 }
8422 }
8423 else {
8424 /* if no resolvers section associated to this server
8425 * we can clean up the associated resolution structure
8426 */
8427 if (newsrv->resolution) {
8428 free(newsrv->resolution->hostname_dn);
8429 newsrv->resolution->hostname_dn = NULL;
8430 free(newsrv->resolution);
8431 newsrv->resolution = NULL;
8432 }
8433 }
8434
Willy Tarreau62c3be22012-01-20 13:12:32 +01008435 next_srv:
8436 newsrv = newsrv->next;
8437 }
8438
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008439 /* We have to initialize the server lookup mechanism depending
8440 * on what LB algorithm was choosen.
8441 */
8442
8443 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8444 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8445 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008446 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8447 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8448 init_server_map(curproxy);
8449 } else {
8450 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8451 fwrr_init_server_groups(curproxy);
8452 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008453 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008454
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008455 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008456 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8457 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8458 fwlc_init_server_tree(curproxy);
8459 } else {
8460 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8461 fas_init_server_tree(curproxy);
8462 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008463 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008464
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008465 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008466 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8467 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8468 chash_init_server_tree(curproxy);
8469 } else {
8470 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8471 init_server_map(curproxy);
8472 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008473 break;
8474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008475
8476 if (curproxy->options & PR_O_LOGASAP)
8477 curproxy->to_log &= ~LW_BYTES;
8478
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008479 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008480 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8481 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008482 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8483 proxy_type_str(curproxy), curproxy->id);
8484 err_code |= ERR_WARN;
8485 }
8486
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008487 if (curproxy->mode != PR_MODE_HTTP) {
8488 int optnum;
8489
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008490 if (curproxy->uri_auth) {
8491 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8492 proxy_type_str(curproxy), curproxy->id);
8493 err_code |= ERR_WARN;
8494 curproxy->uri_auth = NULL;
8495 }
8496
Willy Tarreau87cf5142011-08-19 22:57:24 +02008497 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008498 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8499 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8500 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008501 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008502 }
8503
8504 if (curproxy->options & PR_O_ORGTO) {
8505 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8506 "originalto", proxy_type_str(curproxy), curproxy->id);
8507 err_code |= ERR_WARN;
8508 curproxy->options &= ~PR_O_ORGTO;
8509 }
8510
8511 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8512 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8513 (curproxy->cap & cfg_opts[optnum].cap) &&
8514 (curproxy->options & cfg_opts[optnum].val)) {
8515 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8516 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8517 err_code |= ERR_WARN;
8518 curproxy->options &= ~cfg_opts[optnum].val;
8519 }
8520 }
8521
8522 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8523 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8524 (curproxy->cap & cfg_opts2[optnum].cap) &&
8525 (curproxy->options2 & cfg_opts2[optnum].val)) {
8526 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8527 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8528 err_code |= ERR_WARN;
8529 curproxy->options2 &= ~cfg_opts2[optnum].val;
8530 }
8531 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008532
Willy Tarreau29fbe512015-08-20 19:35:14 +02008533#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008534 if (curproxy->conn_src.bind_hdr_occ) {
8535 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008536 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008537 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008538 err_code |= ERR_WARN;
8539 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008540#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008541 }
8542
Willy Tarreaubaaee002006-06-26 02:48:02 +02008543 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008544 * ensure that we're not cross-dressing a TCP server into HTTP.
8545 */
8546 newsrv = curproxy->srv;
8547 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008548 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008549 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8550 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008551 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008552 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008553
Willy Tarreau0cec3312011-10-31 13:49:26 +01008554 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8555 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8556 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8557 err_code |= ERR_WARN;
8558 }
8559
Willy Tarreauc93cd162014-05-13 15:54:22 +02008560 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008561 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8562 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8563 err_code |= ERR_WARN;
8564 }
8565
Willy Tarreau29fbe512015-08-20 19:35:14 +02008566#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008567 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8568 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008569 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 +01008570 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008571 err_code |= ERR_WARN;
8572 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008573#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008574
8575 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8576 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8577 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8578 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8579 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8580 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",
8581 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8582 err_code |= ERR_WARN;
8583 }
8584
8585
8586 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8587 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",
8588 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8589 err_code |= ERR_WARN;
8590 }
8591 }
8592
Willy Tarreau21d2af32008-02-14 20:25:24 +01008593 newsrv = newsrv->next;
8594 }
8595
Willy Tarreaue42bd962014-09-16 16:21:19 +02008596 /* check if we have a frontend with "tcp-request content" looking at L7
8597 * with no inspect-delay
8598 */
8599 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8600 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008601 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008602 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008603 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008604 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008605 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008606 break;
8607 }
8608
8609 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8610 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8611 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8612 " This means that these rules will randomly find their contents. This can be fixed by"
8613 " setting the tcp-request inspect-delay.\n",
8614 proxy_type_str(curproxy), curproxy->id);
8615 err_code |= ERR_WARN;
8616 }
8617 }
8618
Christopher Fauletd7c91962015-04-30 11:48:27 +02008619 /* Check filter configuration, if any */
8620 cfgerr += flt_check(curproxy);
8621
Willy Tarreauc1a21672009-08-16 22:37:44 +02008622 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008623 if (!curproxy->accept)
8624 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008625
Willy Tarreauc1a21672009-08-16 22:37:44 +02008626 if (curproxy->tcp_req.inspect_delay ||
8627 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008628 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008629
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008630 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008631 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008632 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008633 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008634
8635 /* both TCP and HTTP must check switching rules */
8636 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008637
8638 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008639 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008640 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8641 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 +01008642 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008643 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8644 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008645 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008646 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008647 }
8648
8649 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008650 if (curproxy->tcp_req.inspect_delay ||
8651 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8652 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8653
Emeric Brun97679e72010-09-23 17:56:44 +02008654 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8655 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8656
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008657 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008658 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008659 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008660 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008661
8662 /* If the backend does requires RDP cookie persistence, we have to
8663 * enable the corresponding analyser.
8664 */
8665 if (curproxy->options2 & PR_O2_RDPC_PRST)
8666 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008667
8668 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008669 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008670 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8671 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 +01008672 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008673 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8674 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008675 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008676 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008677 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008678 }
8679
8680 /***********************************************************/
8681 /* At this point, target names have already been resolved. */
8682 /***********************************************************/
8683
8684 /* Check multi-process mode compatibility */
8685
8686 if (global.nbproc > 1 && global.stats_fe) {
8687 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8688 unsigned long mask;
8689
8690 mask = nbits(global.nbproc);
8691 if (global.stats_fe->bind_proc)
8692 mask &= global.stats_fe->bind_proc;
8693
8694 if (bind_conf->bind_proc)
8695 mask &= bind_conf->bind_proc;
8696
8697 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008698 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008699 break;
8700 }
8701 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8702 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");
8703 }
8704 }
8705
8706 /* Make each frontend inherit bind-process from its listeners when not specified. */
8707 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8708 if (curproxy->bind_proc)
8709 continue;
8710
8711 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8712 unsigned long mask;
8713
Willy Tarreaue428b082015-05-04 21:57:58 +02008714 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008715 curproxy->bind_proc |= mask;
8716 }
8717
8718 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008719 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008720 }
8721
8722 if (global.stats_fe) {
8723 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8724 unsigned long mask;
8725
Cyril Bonté06181952016-02-24 00:14:54 +01008726 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008727 global.stats_fe->bind_proc |= mask;
8728 }
8729 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008730 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008731 }
8732
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008733 /* propagate bindings from frontends to backends. Don't do it if there
8734 * are any fatal errors as we must not call it with unresolved proxies.
8735 */
8736 if (!cfgerr) {
8737 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8738 if (curproxy->cap & PR_CAP_FE)
8739 propagate_processes(curproxy, NULL);
8740 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008741 }
8742
8743 /* Bind each unbound backend to all processes when not specified. */
8744 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8745 if (curproxy->bind_proc)
8746 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008747 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008748 }
8749
8750 /*******************************************************/
8751 /* At this step, all proxies have a non-null bind_proc */
8752 /*******************************************************/
8753
8754 /* perform the final checks before creating tasks */
8755
8756 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8757 struct listener *listener;
8758 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008759
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008760 /* Configure SSL for each bind line.
8761 * Note: if configuration fails at some point, the ->ctx member
8762 * remains NULL so that listeners can later detach.
8763 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008764 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008765 if (bind_conf->xprt->prepare_bind_conf &&
8766 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008767 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008768 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008769
Willy Tarreaue6b98942007-10-29 01:09:36 +01008770 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008771 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008772 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008773 int nbproc;
8774
8775 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008776 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008777 nbits(global.nbproc));
8778
8779 if (!nbproc) /* no intersection between listener and frontend */
8780 nbproc = 1;
8781
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008782 if (!listener->luid) {
8783 /* listener ID not set, use automatic numbering with first
8784 * spare entry starting with next_luid.
8785 */
8786 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8787 listener->conf.id.key = listener->luid = next_id;
8788 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008789 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008790 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008791
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008792 /* enable separate counters */
8793 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008794 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008795 if (!listener->name)
8796 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008797 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008798
Willy Tarreaue6b98942007-10-29 01:09:36 +01008799 if (curproxy->options & PR_O_TCP_NOLING)
8800 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008801 if (!listener->maxconn)
8802 listener->maxconn = curproxy->maxconn;
8803 if (!listener->backlog)
8804 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008805 if (!listener->maxaccept)
8806 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8807
8808 /* we want to have an optimal behaviour on single process mode to
8809 * maximize the work at once, but in multi-process we want to keep
8810 * some fairness between processes, so we target half of the max
8811 * number of events to be balanced over all the processes the proxy
8812 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8813 * used to disable the limit.
8814 */
8815 if (listener->maxaccept > 0) {
8816 if (nbproc > 1)
8817 listener->maxaccept = (listener->maxaccept + 1) / 2;
8818 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8819 }
8820
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008821 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008822 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008823 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008824 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008825
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008826 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008827 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008828
Willy Tarreau620408f2016-10-21 16:37:51 +02008829 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8830 listener->options |= LI_O_TCP_L5_RULES;
8831
Willy Tarreaude3041d2010-05-31 10:56:17 +02008832 if (curproxy->mon_mask.s_addr)
8833 listener->options |= LI_O_CHK_MONNET;
8834
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008835 /* smart accept mode is automatic in HTTP mode */
8836 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008837 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008838 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8839 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008840 }
8841
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008842 /* Release unused SSL configs */
8843 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008844 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8845 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008846 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008847
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008848 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008849 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008850 int count, maxproc = 0;
8851
8852 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008853 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008854 if (count > maxproc)
8855 maxproc = count;
8856 }
8857 /* backends have 0, frontends have 1 or more */
8858 if (maxproc != 1)
8859 Warning("Proxy '%s': in multi-process mode, stats will be"
8860 " limited to process assigned to the current request.\n",
8861 curproxy->id);
8862
Willy Tarreau102df612014-05-07 23:56:38 +02008863 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8864 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8865 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008866 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008867 }
Willy Tarreau102df612014-05-07 23:56:38 +02008868 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8869 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8870 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008871 }
8872 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008873
8874 /* create the task associated with the proxy */
8875 curproxy->task = task_new();
8876 if (curproxy->task) {
8877 curproxy->task->context = curproxy;
8878 curproxy->task->process = manage_proxy;
8879 /* no need to queue, it will be done automatically if some
8880 * listener gets limited.
8881 */
8882 curproxy->task->expire = TICK_ETERNITY;
8883 } else {
8884 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8885 curproxy->id);
8886 cfgerr++;
8887 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008888 }
8889
Willy Tarreaufbb78422011-06-05 15:38:35 +02008890 /* automatically compute fullconn if not set. We must not do it in the
8891 * loop above because cross-references are not yet fully resolved.
8892 */
8893 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8894 /* If <fullconn> is not set, let's set it to 10% of the sum of
8895 * the possible incoming frontend's maxconns.
8896 */
8897 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008898 /* we have the sum of the maxconns in <total>. We only
8899 * keep 10% of that sum to set the default fullconn, with
8900 * a hard minimum of 1 (to avoid a divide by zero).
8901 */
Emeric Brun3f783572017-01-12 11:21:28 +01008902 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008903 if (!curproxy->fullconn)
8904 curproxy->fullconn = 1;
8905 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008906 }
8907
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008908 /*
8909 * Recount currently required checks.
8910 */
8911
8912 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8913 int optnum;
8914
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008915 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8916 if (curproxy->options & cfg_opts[optnum].val)
8917 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008918
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008919 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8920 if (curproxy->options2 & cfg_opts2[optnum].val)
8921 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008922 }
8923
Willy Tarreau0fca4832015-05-01 19:12:05 +02008924 /* compute the required process bindings for the peers */
8925 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8926 if (curproxy->table.peers.p)
8927 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8928
Willy Tarreau122541c2011-09-07 21:24:49 +02008929 if (peers) {
8930 struct peers *curpeers = peers, **last;
8931 struct peer *p, *pb;
8932
Willy Tarreau1e273012015-05-01 19:15:17 +02008933 /* Remove all peers sections which don't have a valid listener,
8934 * which are not used by any table, or which are bound to more
8935 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008936 */
8937 last = &peers;
8938 while (*last) {
8939 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008940
8941 if (curpeers->state == PR_STSTOPPED) {
8942 /* the "disabled" keyword was present */
8943 if (curpeers->peers_fe)
8944 stop_proxy(curpeers->peers_fe);
8945 curpeers->peers_fe = NULL;
8946 }
8947 else if (!curpeers->peers_fe) {
8948 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8949 curpeers->id, localpeer);
8950 }
David Carliere6c39412015-07-02 07:00:17 +00008951 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008952 /* either it's totally stopped or too much used */
8953 if (curpeers->peers_fe->bind_proc) {
8954 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008955 "running in different processes (%d different ones). "
8956 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008957 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008958 cfgerr++;
8959 }
8960 stop_proxy(curpeers->peers_fe);
8961 curpeers->peers_fe = NULL;
8962 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008963 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008964 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008965 last = &curpeers->next;
8966 continue;
8967 }
8968
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008969 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008970 p = curpeers->remote;
8971 while (p) {
8972 pb = p->next;
8973 free(p->id);
8974 free(p);
8975 p = pb;
8976 }
8977
8978 /* Destroy and unlink this curpeers section.
8979 * Note: curpeers is backed up into *last.
8980 */
8981 free(curpeers->id);
8982 curpeers = curpeers->next;
8983 free(*last);
8984 *last = curpeers;
8985 }
8986 }
8987
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008988 /* initialize stick-tables on backend capable proxies. This must not
8989 * be done earlier because the data size may be discovered while parsing
8990 * other proxies.
8991 */
8992 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8993 if (curproxy->state == PR_STSTOPPED)
8994 continue;
8995
8996 if (!stktable_init(&curproxy->table)) {
8997 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8998 cfgerr++;
8999 }
9000 }
9001
Simon Horman0d16a402015-01-30 11:22:58 +09009002 if (mailers) {
9003 struct mailers *curmailers = mailers, **last;
9004 struct mailer *m, *mb;
9005
9006 /* Remove all mailers sections which don't have a valid listener.
9007 * This can happen when a mailers section is never referenced.
9008 */
9009 last = &mailers;
9010 while (*last) {
9011 curmailers = *last;
9012 if (curmailers->users) {
9013 last = &curmailers->next;
9014 continue;
9015 }
9016
9017 Warning("Removing incomplete section 'mailers %s'.\n",
9018 curmailers->id);
9019
9020 m = curmailers->mailer_list;
9021 while (m) {
9022 mb = m->next;
9023 free(m->id);
9024 free(m);
9025 m = mb;
9026 }
9027
9028 /* Destroy and unlink this curmailers section.
9029 * Note: curmailers is backed up into *last.
9030 */
9031 free(curmailers->id);
9032 curmailers = curmailers->next;
9033 free(*last);
9034 *last = curmailers;
9035 }
9036 }
9037
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009038 /* Update server_state_file_name to backend name if backend is supposed to use
9039 * a server-state file locally defined and none has been provided */
9040 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9041 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9042 curproxy->server_state_file_name == NULL)
9043 curproxy->server_state_file_name = strdup(curproxy->id);
9044 }
9045
Willy Tarreau34eb6712011-10-24 18:15:04 +02009046 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009047 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009048 MEM_F_SHARED);
9049
Willy Tarreaubb925012009-07-23 13:36:36 +02009050 if (cfgerr > 0)
9051 err_code |= ERR_ALERT | ERR_FATAL;
9052 out:
9053 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009054}
9055
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009056/*
9057 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9058 * parsing sessions.
9059 */
9060void cfg_register_keywords(struct cfg_kw_list *kwl)
9061{
9062 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9063}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009064
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009065/*
9066 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9067 */
9068void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9069{
9070 LIST_DEL(&kwl->list);
9071 LIST_INIT(&kwl->list);
9072}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009073
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009074/* this function register new section in the haproxy configuration file.
9075 * <section_name> is the name of this new section and <section_parser>
9076 * is the called parser. If two section declaration have the same name,
9077 * only the first declared is used.
9078 */
9079int cfg_register_section(char *section_name,
9080 int (*section_parser)(const char *, int, char **, int))
9081{
9082 struct cfg_section *cs;
9083
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009084 list_for_each_entry(cs, &sections, list) {
9085 if (strcmp(cs->section_name, section_name) == 0) {
9086 Alert("register section '%s': already registered.\n", section_name);
9087 return 0;
9088 }
9089 }
9090
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009091 cs = calloc(1, sizeof(*cs));
9092 if (!cs) {
9093 Alert("register section '%s': out of memory.\n", section_name);
9094 return 0;
9095 }
9096
9097 cs->section_name = section_name;
9098 cs->section_parser = section_parser;
9099
9100 LIST_ADDQ(&sections, &cs->list);
9101
9102 return 1;
9103}
9104
Willy Tarreaubaaee002006-06-26 02:48:02 +02009105/*
David Carlier845efb52015-09-25 11:49:18 +01009106 * free all config section entries
9107 */
9108void cfg_unregister_sections(void)
9109{
9110 struct cfg_section *cs, *ics;
9111
9112 list_for_each_entry_safe(cs, ics, &sections, list) {
9113 LIST_DEL(&cs->list);
9114 free(cs);
9115 }
9116}
9117
Christopher Faulet7110b402016-10-26 11:09:44 +02009118void cfg_backup_sections(struct list *backup_sections)
9119{
9120 struct cfg_section *cs, *ics;
9121
9122 list_for_each_entry_safe(cs, ics, &sections, list) {
9123 LIST_DEL(&cs->list);
9124 LIST_ADDQ(backup_sections, &cs->list);
9125 }
9126}
9127
9128void cfg_restore_sections(struct list *backup_sections)
9129{
9130 struct cfg_section *cs, *ics;
9131
9132 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9133 LIST_DEL(&cs->list);
9134 LIST_ADDQ(&sections, &cs->list);
9135 }
9136}
9137
Willy Tarreau659fbf02016-05-26 17:55:28 +02009138__attribute__((constructor))
9139static void cfgparse_init(void)
9140{
9141 /* Register internal sections */
9142 cfg_register_section("listen", cfg_parse_listen);
9143 cfg_register_section("frontend", cfg_parse_listen);
9144 cfg_register_section("backend", cfg_parse_listen);
9145 cfg_register_section("defaults", cfg_parse_listen);
9146 cfg_register_section("global", cfg_parse_global);
9147 cfg_register_section("userlist", cfg_parse_users);
9148 cfg_register_section("peers", cfg_parse_peers);
9149 cfg_register_section("mailers", cfg_parse_mailers);
9150 cfg_register_section("namespace_list", cfg_parse_netns);
9151 cfg_register_section("resolvers", cfg_parse_resolvers);
9152}
9153
David Carlier845efb52015-09-25 11:49:18 +01009154/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009155 * Local variables:
9156 * c-indent-level: 8
9157 * c-basic-offset: 8
9158 * End:
9159 */