blob: 47d33cf1b05ff72b42382e90bf8d6bdb3f41899f [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
William Lallemand9ed62032016-11-21 17:49:11 +010054#include <types/stats.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055
Willy Tarreaueb0c6142007-05-07 00:53:22 +020056#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010057#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020059#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020061#include <proto/compression.h>
William Lallemand9ed62032016-11-21 17:49:11 +010062#include <proto/stats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020063#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020064#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020065#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020066#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010067#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020068#include <proto/lb_fwlc.h>
69#include <proto/lb_fwrr.h>
70#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020071#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020073#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010074#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020075#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010076#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010077#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020078#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020079#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020080#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020082#include <proto/stream.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010083#include <proto/stick_table.h>
Willy Tarreau39713102016-11-25 15:49:32 +010084#include <proto/task.h>
85#include <proto/tcp_rules.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
87
Willy Tarreauf3c69202006-07-09 16:42:34 +020088/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
89 * ssl-hello-chk option to ensure that the remote server speaks SSL.
90 *
91 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
92 */
93const char sslv3_client_hello_pkt[] = {
94 "\x16" /* ContentType : 0x16 = Hanshake */
95 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
96 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
97 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
98 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
99 "\x03\x00" /* Hello Version : 0x0300 = v3 */
100 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
101 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
102 "\x00" /* Session ID length : empty (no session ID) */
103 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
104 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
105 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
106 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
107 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
108 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
109 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
110 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
111 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
112 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
113 "\x00\x38" "\x00\x39" "\x00\x3A"
114 "\x01" /* Compression Length : 0x01 = 1 byte for types */
115 "\x00" /* Compression Type : 0x00 = NULL compression */
116};
117
Willy Tarreau3842f002009-06-14 11:39:52 +0200118/* various keyword modifiers */
119enum kw_mod {
120 KWM_STD = 0, /* normal */
121 KWM_NO, /* "no" prefixed before the keyword */
122 KWM_DEF, /* "default" prefixed before the keyword */
123};
124
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100125/* permit to store configuration section */
126struct cfg_section {
127 struct list list;
128 char *section_name;
129 int (*section_parser)(const char *, int, char **, int);
130};
131
132/* Used to chain configuration sections definitions. This list
133 * stores struct cfg_section
134 */
135struct list sections = LIST_HEAD_INIT(sections);
136
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100138struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139 const char *name;
140 unsigned int val;
141 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100142 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144};
145
146/* proxy->options */
147static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
150 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
151 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
152 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
153 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
154 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200156 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200157 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100158 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
160 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
161 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100163#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100165#else
166 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100167#endif
168
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100170};
171
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100172/* proxy->options2 */
173static const struct cfg_opt cfg_opts2[] =
174{
175#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
177 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100179#else
180 { "splice-request", 0, 0, 0, 0 },
181 { "splice-response", 0, 0, 0, 0 },
182 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100183#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100184 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
185 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
186 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
187 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
188 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
189 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
190 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
192 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400193 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100194 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200195 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200196 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100197 { NULL, 0, 0, 0 }
198};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199
Willy Tarreau6daf3432008-01-22 16:44:08 +0100200static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
202int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100203int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Christopher Faulet79bdef32016-11-04 22:36:15 +0100204char *cfg_scope = NULL; /* the current scope during the configuration parsing */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200206/* List head of all known configuration keywords */
207static struct cfg_kw_list cfg_keywords = {
208 .list = LIST_HEAD_INIT(cfg_keywords.list)
209};
210
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211/*
212 * converts <str> to a list of listeners which are dynamically allocated.
213 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
214 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
215 * - <port> is a numerical port from 1 to 65535 ;
216 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
217 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
219 * not NULL, it must be a valid pointer to either NULL or a freeable area that
220 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223{
224 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 int port, end;
227
228 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200229
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100232 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
234 str = next;
235 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100236 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 *next++ = 0;
238 }
239
Willy Tarreau48ef4c92017-01-06 18:32:38 +0100240 ss2 = str2sa_range(str, NULL, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200241 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200242 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 if (!ss2)
244 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port || !end) {
253 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
254 goto fail;
255 }
256
Emeric Bruned760922010-10-22 17:59:25 +0200257 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
261
262 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100267 else if (ss2->ss_family == AF_UNSPEC) {
268 socklen_t addr_len;
269
270 /* We want to attach to an already bound fd whose number
271 * is in the addr part of ss2 when cast to sockaddr_in.
272 * Note that by definition there is a single listener.
273 * We still have to determine the address family to
274 * register the correct protocol.
275 */
276 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
277 addr_len = sizeof(*ss2);
278 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
279 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
280 goto fail;
281 }
282
283 port = end = get_host_port(ss2);
284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100286 /* OK the address looks correct */
Vincent Bernat6e615892016-05-18 16:17:44 +0200287 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100288
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200290 l = calloc(1, sizeof(*l));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100291 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200292 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
293 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
Willy Tarreau4348fad2012-09-20 16:48:07 +0200294 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau40aa0702013-03-10 23:51:38 +0100296 l->fd = fd;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200297 memcpy(&l->addr, &ss, sizeof(ss));
Willy Tarreaue6b98942007-10-29 01:09:36 +0100298 l->state = LI_INIT;
299
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100300 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100302 tcpv4_add_listener(l);
303 }
Emeric Bruned760922010-10-22 17:59:25 +0200304 else if (ss.ss_family == AF_INET6) {
305 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
306 tcpv6_add_listener(l);
307 }
308 else {
Emeric Bruned760922010-10-22 17:59:25 +0200309 uxst_add_listener(l);
310 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200311
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200312 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100313 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200314 } /* end for(port) */
315 } /* end while(next) */
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 fail:
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321}
322
William Lallemand6e62fb62015-04-28 16:55:23 +0200323/*
Willy Tarreauece9b072016-12-21 22:41:44 +0100324 * Report an error in <msg> when there are too many arguments. This version is
325 * intended to be used by keyword parsers so that the message will be included
326 * into the general error message. The index is the current keyword in args.
327 * Return 0 if the number of argument is correct, otherwise build a message and
328 * return 1. Fill err_code with an ERR_ALERT and an ERR_FATAL if not null. The
329 * message may also be null, it will simply not be produced (useful to check only).
330 * <msg> and <err_code> are only affected on error.
331 */
332int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_code)
333{
334 int i;
335
336 if (!*args[index + maxarg + 1])
337 return 0;
338
339 if (msg) {
340 *msg = NULL;
341 memprintf(msg, "%s", args[0]);
342 for (i = 1; i <= index; i++)
343 memprintf(msg, "%s %s", *msg, args[i]);
344
345 memprintf(msg, "'%s' cannot handle unexpected argument '%s'.", *msg, args[index + maxarg + 1]);
346 }
347 if (err_code)
348 *err_code |= ERR_ALERT | ERR_FATAL;
349
350 return 1;
351}
352
353/*
354 * same as too_many_args_idx with a 0 index
355 */
356int too_many_args(int maxarg, char **args, char **msg, int *err_code)
357{
358 return too_many_args_idx(maxarg, 0, args, msg, err_code);
359}
360
361/*
William Lallemand6e62fb62015-04-28 16:55:23 +0200362 * Report a fatal Alert when there is too much arguments
363 * The index is the current keyword in args
364 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
365 * Fill err_code with an ERR_ALERT and an ERR_FATAL
366 */
367int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
368{
369 char *kw = NULL;
370 int i;
371
372 if (!*args[index + maxarg + 1])
373 return 0;
374
375 memprintf(&kw, "%s", args[0]);
376 for (i = 1; i <= index; i++) {
377 memprintf(&kw, "%s %s", kw, args[i]);
378 }
379
380 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
381 free(kw);
382 *err_code |= ERR_ALERT | ERR_FATAL;
383 return 1;
384}
385
386/*
387 * same as alertif_too_many_args_idx with a 0 index
388 */
389int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
390{
391 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
392}
393
Willy Tarreau620408f2016-10-21 16:37:51 +0200394/* Report a warning if a rule is placed after a 'tcp-request session' rule.
395 * Return 1 if the warning has been emitted, otherwise 0.
396 */
397int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
398{
399 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
400 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
401 file, line, arg);
402 return 1;
403 }
404 return 0;
405}
406
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200407/* Report a warning if a rule is placed after a 'tcp-request content' rule.
408 * Return 1 if the warning has been emitted, otherwise 0.
409 */
410int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
411{
412 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
413 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
414 file, line, arg);
415 return 1;
416 }
417 return 0;
418}
419
Willy Tarreau61d18892009-03-31 10:49:21 +0200420/* Report a warning if a rule is placed after a 'block' rule.
421 * Return 1 if the warning has been emitted, otherwise 0.
422 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200425 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200426 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
427 file, line, arg);
428 return 1;
429 }
430 return 0;
431}
432
Willy Tarreau5002f572014-04-23 01:32:02 +0200433/* Report a warning if a rule is placed after an 'http_request' rule.
434 * Return 1 if the warning has been emitted, otherwise 0.
435 */
436int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
437{
438 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
439 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
440 file, line, arg);
441 return 1;
442 }
443 return 0;
444}
445
Willy Tarreau61d18892009-03-31 10:49:21 +0200446/* Report a warning if a rule is placed after a reqrewrite rule.
447 * Return 1 if the warning has been emitted, otherwise 0.
448 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100449int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200450{
451 if (proxy->req_exp) {
452 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
453 file, line, arg);
454 return 1;
455 }
456 return 0;
457}
458
459/* Report a warning if a rule is placed after a reqadd rule.
460 * Return 1 if the warning has been emitted, otherwise 0.
461 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100462int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200463{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100464 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200465 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
466 file, line, arg);
467 return 1;
468 }
469 return 0;
470}
471
472/* Report a warning if a rule is placed after a redirect rule.
473 * Return 1 if the warning has been emitted, otherwise 0.
474 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
478 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
479 file, line, arg);
480 return 1;
481 }
482 return 0;
483}
484
485/* Report a warning if a rule is placed after a 'use_backend' rule.
486 * Return 1 if the warning has been emitted, otherwise 0.
487 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100488int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200489{
490 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
491 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
492 file, line, arg);
493 return 1;
494 }
495 return 0;
496}
497
Willy Tarreauee445d92014-04-23 01:39:04 +0200498/* Report a warning if a rule is placed after a 'use-server' rule.
499 * Return 1 if the warning has been emitted, otherwise 0.
500 */
501int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
502{
503 if (!LIST_ISEMPTY(&proxy->server_rules)) {
504 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
505 file, line, arg);
506 return 1;
507 }
508 return 0;
509}
510
Willy Tarreaud39ad442016-11-25 15:16:12 +0100511/* report a warning if a redirect rule is dangerously placed */
512int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau620408f2016-10-21 16:37:51 +0200513{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100514 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200515 warnif_rule_after_use_server(proxy, file, line, arg);
516}
517
Willy Tarreaud39ad442016-11-25 15:16:12 +0100518/* report a warning if a reqadd rule is dangerously placed */
519int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200520{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100521 return warnif_rule_after_redirect(proxy, file, line, arg) ||
522 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200523}
524
Willy Tarreaud39ad442016-11-25 15:16:12 +0100525/* report a warning if a reqxxx rule is dangerously placed */
526int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200527{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100528 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
529 warnif_misplaced_reqadd(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200530}
531
532/* report a warning if an http-request rule is dangerously placed */
533int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
534{
Willy Tarreau61d18892009-03-31 10:49:21 +0200535 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
Willy Tarreaud39ad442016-11-25 15:16:12 +0100536 warnif_misplaced_reqxxx(proxy, file, line, arg);;
Willy Tarreau61d18892009-03-31 10:49:21 +0200537}
538
Willy Tarreaud39ad442016-11-25 15:16:12 +0100539/* report a warning if a block rule is dangerously placed */
540int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200541{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100542 return warnif_rule_after_http_req(proxy, file, line, arg) ||
543 warnif_misplaced_http_req(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200544}
545
Willy Tarreaud39ad442016-11-25 15:16:12 +0100546/* report a warning if a "tcp request content" rule is dangerously placed */
547int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200548{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100549 return warnif_rule_after_block(proxy, file, line, arg) ||
550 warnif_misplaced_block(proxy, file, line, arg);
Willy Tarreauee445d92014-04-23 01:39:04 +0200551}
552
Willy Tarreaud39ad442016-11-25 15:16:12 +0100553/* report a warning if a "tcp request session" rule is dangerously placed */
554int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreauee445d92014-04-23 01:39:04 +0200555{
Willy Tarreaud39ad442016-11-25 15:16:12 +0100556 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
557 warnif_misplaced_tcp_cont(proxy, file, line, arg);
558}
559
560/* report a warning if a "tcp request connection" rule is dangerously placed */
561int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
562{
563 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
564 warnif_misplaced_tcp_sess(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200565}
566
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100567/* Report it if a request ACL condition uses some keywords that are incompatible
568 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
569 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
570 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100571 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100572static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100573{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100574 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200575 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100576
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100577 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100578 return 0;
579
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100580 acl = acl_cond_conflicts(cond, where);
581 if (acl) {
582 if (acl->name && *acl->name)
583 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
584 file, line, acl->name, sample_ckp_names(where));
585 else
586 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200587 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100588 return ERR_WARN;
589 }
590 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100591 return 0;
592
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100593 if (acl->name && *acl->name)
594 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200595 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100596 else
597 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200598 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100599 return ERR_WARN;
600}
601
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200603 * parse a line in a <global> section. Returns the error code, 0 if OK, or
604 * any combination of :
605 * - ERR_ABORT: must abort ASAP
606 * - ERR_FATAL: we can continue parsing but not start the service
607 * - ERR_WARN: a warning has been emitted
608 * - ERR_ALERT: an alert has been emitted
609 * Only the two first ones can stop processing, the two others are just
610 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200612int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613{
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200615 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616
617 if (!strcmp(args[0], "global")) { /* new section */
618 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200619 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 }
622 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200623 if (alertif_too_many_args(0, file, linenum, args, &err_code))
624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 global.mode |= MODE_DAEMON;
626 }
627 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200628 if (alertif_too_many_args(0, file, linenum, args, &err_code))
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 global.mode |= MODE_DEBUG;
631 }
632 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100635 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200637 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100640 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100647 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100650 global.tune.options &= ~GTUNE_USE_SPLICE;
651 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200652 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200655 global.tune.options &= ~GTUNE_USE_GAI;
656 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000657 else if (!strcmp(args[0], "noreuseport")) {
658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
660 global.tune.options &= ~GTUNE_USE_REUSEPORT;
661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 global.mode |= MODE_QUIET;
666 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200667 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(1, file, linenum, args, &err_code))
669 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200670 if (global.tune.maxpollevents != 0) {
671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT;
673 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200674 }
675 if (*(args[1]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 global.tune.maxpollevents = atol(args[1]);
681 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100682 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200683 if (alertif_too_many_args(1, file, linenum, args, &err_code))
684 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100685 if (global.tune.maxaccept != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 global.tune.maxaccept = atol(args[1]);
696 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200697 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200698 if (alertif_too_many_args(1, file, linenum, args, &err_code))
699 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.chksize = atol(args[1]);
706 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100707 else if (!strcmp(args[0], "tune.recv_enough")) {
708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
709 goto out;
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 global.tune.recv_enough = atol(args[1]);
716 }
Willy Tarreau33cb0652014-12-23 22:52:37 +0100717 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
719 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100720 if (*(args[1]) == 0) {
721 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
722 err_code |= ERR_ALERT | ERR_FATAL;
723 goto out;
724 }
725 global.tune.buf_limit = atol(args[1]);
726 if (global.tune.buf_limit) {
727 if (global.tune.buf_limit < 3)
728 global.tune.buf_limit = 3;
729 if (global.tune.buf_limit <= global.tune.reserved_bufs)
730 global.tune.buf_limit = global.tune.reserved_bufs + 1;
731 }
732 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100733 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741 global.tune.reserved_bufs = atol(args[1]);
742 if (global.tune.reserved_bufs < 2)
743 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100744 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
745 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100746 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200747 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200756 if (global.tune.bufsize <= 0) {
757 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
760 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100761 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100762 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200763 }
764 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200765 if (alertif_too_many_args(1, file, linenum, args, &err_code))
766 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200773 if (global.tune.maxrewrite < 0) {
774 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200778 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100779 else if (!strcmp(args[0], "tune.idletimer")) {
780 unsigned int idle;
781 const char *res;
782
William Lallemand1a748ae2015-05-19 16:37:23 +0200783 if (alertif_too_many_args(1, file, linenum, args, &err_code))
784 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100785 if (*(args[1]) == 0) {
786 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
789 }
790
791 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
792 if (res) {
793 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
794 file, linenum, *res, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798
799 if (idle > 65535) {
800 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.idle_timer = idle;
805 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100806 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200807 if (alertif_too_many_args(1, file, linenum, args, &err_code))
808 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100809 if (global.tune.client_rcvbuf != 0) {
810 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
811 err_code |= ERR_ALERT;
812 goto out;
813 }
814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.client_rcvbuf = atol(args[1]);
820 }
821 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100824 if (global.tune.server_rcvbuf != 0) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT;
827 goto out;
828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.server_rcvbuf = atol(args[1]);
835 }
836 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200837 if (alertif_too_many_args(1, file, linenum, args, &err_code))
838 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100839 if (global.tune.client_sndbuf != 0) {
840 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT;
842 goto out;
843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.client_sndbuf = atol(args[1]);
850 }
851 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100854 if (global.tune.server_sndbuf != 0) {
855 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT;
857 goto out;
858 }
859 if (*(args[1]) == 0) {
860 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 global.tune.server_sndbuf = atol(args[1]);
865 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200866 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200867 if (alertif_too_many_args(1, file, linenum, args, &err_code))
868 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.tune.pipesize = atol(args[1]);
875 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100876 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200877 if (alertif_too_many_args(1, file, linenum, args, &err_code))
878 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884 global.tune.cookie_len = atol(args[1]) + 1;
885 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200886 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200887 if (alertif_too_many_args(1, file, linenum, args, &err_code))
888 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200889 if (*(args[1]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 global.tune.max_http_hdr = atol(args[1]);
895 }
William Lallemandf3747832012-11-09 12:33:10 +0100896 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200897 if (alertif_too_many_args(1, file, linenum, args, &err_code))
898 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100899 if (*args[1]) {
900 global.tune.comp_maxlevel = atoi(args[1]);
901 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
902 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
903 file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 } else {
908 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
909 file, linenum, args[0]);
910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
913 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200914 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
915 if (*args[1]) {
916 global.tune.pattern_cache = atoi(args[1]);
917 if (global.tune.pattern_cache < 0) {
918 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
919 file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923 } else {
924 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
925 file, linenum, args[0]);
926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
928 }
929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200931 if (alertif_too_many_args(1, file, linenum, args, &err_code))
932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200934 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +0100943 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
944 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
945 err_code |= ERR_WARN;
946 goto out;
947 }
948
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200951 if (alertif_too_many_args(1, file, linenum, args, &err_code))
952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200954 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT;
956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
Baptiste Assmann776e5182016-03-11 17:21:15 +0100963 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
964 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
965 err_code |= ERR_WARN;
966 goto out;
967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
Simon Horman98637e52014-06-20 12:30:16 +0900969 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200970 if (alertif_too_many_args(0, file, linenum, args, &err_code))
971 goto out;
Simon Horman98637e52014-06-20 12:30:16 +0900972 global.external_check = 1;
973 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200974 /* user/group name handling */
975 else if (!strcmp(args[0], "user")) {
976 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +0200977 if (alertif_too_many_args(1, file, linenum, args, &err_code))
978 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200979 if (global.uid != 0) {
980 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT;
982 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200983 }
984 errno = 0;
985 ha_user = getpwnam(args[1]);
986 if (ha_user != NULL) {
987 global.uid = (int)ha_user->pw_uid;
988 }
989 else {
990 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200992 }
993 }
994 else if (!strcmp(args[0], "group")) {
995 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +0200996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
997 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200998 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200999 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT;
1001 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001002 }
1003 errno = 0;
1004 ha_group = getgrnam(args[1]);
1005 if (ha_group != NULL) {
1006 global.gid = (int)ha_group->gr_gid;
1007 }
1008 else {
1009 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001011 }
1012 }
1013 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001015 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 if (*(args[1]) == 0) {
1018 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001023 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1024 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1025 file, linenum, args[0], LONGBITS, global.nbproc);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 }
1030 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001031 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 if (global.maxconn != 0) {
1034 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 global.maxconn = atol(args[1]);
1044#ifdef SYSTEM_MAXCONN
1045 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1046 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1047 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
1050#endif /* SYSTEM_MAXCONN */
1051 }
Emeric Brun850efd52014-01-29 12:24:34 +01001052 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001053 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1054 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
1059 }
1060 if (strcmp(args[1],"none") == 0)
1061 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1062 else if (strcmp(args[1],"required") == 0)
1063 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1064 else {
1065 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068 }
1069 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001070 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001071 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1072 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001073 if (global.cps_lim != 0) {
1074 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1075 err_code |= ERR_ALERT;
1076 goto out;
1077 }
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
1082 }
1083 global.cps_lim = atol(args[1]);
1084 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001085 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001088 if (global.sps_lim != 0) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1090 err_code |= ERR_ALERT;
1091 goto out;
1092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
1097 }
1098 global.sps_lim = atol(args[1]);
1099 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001100 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001101 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1102 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001103 if (global.ssl_lim != 0) {
1104 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1105 err_code |= ERR_ALERT;
1106 goto out;
1107 }
1108 if (*(args[1]) == 0) {
1109 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113 global.ssl_lim = atol(args[1]);
1114 }
William Lallemandd85f9172012-11-09 17:05:39 +01001115 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001116 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1117 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001118 if (*(args[1]) == 0) {
1119 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 global.comp_rate_lim = atoi(args[1]) * 1024;
1124 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001125 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001126 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1127 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001128 if (global.maxpipes != 0) {
1129 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT;
1131 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001132 }
1133 if (*(args[1]) == 0) {
1134 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001137 }
1138 global.maxpipes = atol(args[1]);
1139 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001140 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001141 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1142 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
William Lallemande3a7d992012-11-20 11:25:20 +01001148 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001149 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001150 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001151 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1152 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001153 if (*(args[1]) == 0) {
1154 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto out;
1157 }
1158 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001159 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001160 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001164 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001165
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001167 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 if (global.rlimit_nofile != 0) {
1170 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 global.rlimit_nofile = atol(args[1]);
1180 }
1181 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001182 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 if (global.chroot != NULL) {
1185 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001186 err_code |= ERR_ALERT;
1187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001188 }
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
1194 global.chroot = strdup(args[1]);
1195 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001196 else if (!strcmp(args[0], "description")) {
1197 int i, len=0;
1198 char *d;
1199
1200 if (!*args[1]) {
1201 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1202 file, linenum, args[0]);
1203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
1205 }
1206
Willy Tarreau348acfe2014-04-14 15:00:39 +02001207 for (i = 1; *args[i]; i++)
1208 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001209
1210 if (global.desc)
1211 free(global.desc);
1212
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001213 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001214
Willy Tarreau348acfe2014-04-14 15:00:39 +02001215 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1216 for (i = 2; *args[i]; i++)
1217 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001218 }
1219 else if (!strcmp(args[0], "node")) {
1220 int i;
1221 char c;
1222
William Lallemand1a748ae2015-05-19 16:37:23 +02001223 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1224 goto out;
1225
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001226 for (i=0; args[1][i]; i++) {
1227 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001228 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1229 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001230 break;
1231 }
1232
1233 if (!i || args[1][i]) {
1234 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1235 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1236 file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240
1241 if (global.node)
1242 free(global.node);
1243
1244 global.node = strdup(args[1]);
1245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001247 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 if (global.pidfile != NULL) {
1250 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001251 err_code |= ERR_ALERT;
1252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
1254 if (*(args[1]) == 0) {
1255 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 global.pidfile = strdup(args[1]);
1260 }
Emeric Bruned760922010-10-22 17:59:25 +02001261 else if (!strcmp(args[0], "unix-bind")) {
1262 int cur_arg = 1;
1263 while (*(args[cur_arg])) {
1264 if (!strcmp(args[cur_arg], "prefix")) {
1265 if (global.unix_bind.prefix != NULL) {
1266 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1267 err_code |= ERR_ALERT;
1268 cur_arg += 2;
1269 continue;
1270 }
1271
1272 if (*(args[cur_arg+1]) == 0) {
1273 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1278 cur_arg += 2;
1279 continue;
1280 }
1281
1282 if (!strcmp(args[cur_arg], "mode")) {
1283
1284 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1285 cur_arg += 2;
1286 continue;
1287 }
1288
1289 if (!strcmp(args[cur_arg], "uid")) {
1290
1291 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (!strcmp(args[cur_arg], "gid")) {
1297
1298 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1299 cur_arg += 2;
1300 continue;
1301 }
1302
1303 if (!strcmp(args[cur_arg], "user")) {
1304 struct passwd *user;
1305
1306 user = getpwnam(args[cur_arg + 1]);
1307 if (!user) {
1308 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1309 file, linenum, args[0], args[cur_arg + 1 ]);
1310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
1312 }
1313
1314 global.unix_bind.ux.uid = user->pw_uid;
1315 cur_arg += 2;
1316 continue;
1317 }
1318
1319 if (!strcmp(args[cur_arg], "group")) {
1320 struct group *group;
1321
1322 group = getgrnam(args[cur_arg + 1]);
1323 if (!group) {
1324 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1325 file, linenum, args[0], args[cur_arg + 1 ]);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329
1330 global.unix_bind.ux.gid = group->gr_gid;
1331 cur_arg += 2;
1332 continue;
1333 }
1334
Willy Tarreaub48f9582011-09-05 01:17:06 +02001335 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001336 file, linenum, args[0]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
1340 }
William Lallemand0f99e342011-10-12 17:50:54 +02001341 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1342 /* delete previous herited or defined syslog servers */
1343 struct logsrv *back;
1344 struct logsrv *tmp;
1345
1346 if (*(args[1]) != 0) {
1347 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto out;
1350 }
1351
1352 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1353 LIST_DEL(&tmp->list);
1354 free(tmp);
1355 }
1356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001358 struct sockaddr_storage *sk;
1359 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001360 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001361 int arg = 0;
1362 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001363
William Lallemand1a748ae2015-05-19 16:37:23 +02001364 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1365 goto out;
1366
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 if (*(args[1]) == 0 || *(args[2]) == 0) {
1368 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001369 err_code |= ERR_ALERT | ERR_FATAL;
1370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371 }
William Lallemand0f99e342011-10-12 17:50:54 +02001372
Vincent Bernat02779b62016-04-03 13:48:43 +02001373 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001374
Willy Tarreau18324f52014-06-27 18:10:07 +02001375 /* just after the address, a length may be specified */
1376 if (strcmp(args[arg+2], "len") == 0) {
1377 len = atoi(args[arg+3]);
1378 if (len < 80 || len > 65535) {
1379 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1380 file, linenum, args[arg+3]);
1381 err_code |= ERR_ALERT | ERR_FATAL;
1382 goto out;
1383 }
1384 logsrv->maxlen = len;
1385
1386 /* skip these two args */
1387 arg += 2;
1388 }
1389 else
1390 logsrv->maxlen = MAX_SYSLOG_LEN;
1391
1392 if (logsrv->maxlen > global.max_syslog_len) {
1393 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001394 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1395 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1396 logline = my_realloc2(logline, global.max_syslog_len + 1);
1397 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001398 }
1399
Dragan Dosen1322d092015-09-22 16:05:32 +02001400 /* after the length, a format may be specified */
1401 if (strcmp(args[arg+2], "format") == 0) {
1402 logsrv->format = get_log_format(args[arg+3]);
1403 if (logsrv->format < 0) {
1404 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1405 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001406 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001407 goto out;
1408 }
1409
1410 /* skip these two args */
1411 arg += 2;
1412 }
1413
David Carlier97880bb2016-04-08 10:35:26 +01001414 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1415 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001416 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001417 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001418
Willy Tarreau18324f52014-06-27 18:10:07 +02001419 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001420 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001421 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001422 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001423 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001424 }
1425
William Lallemand0f99e342011-10-12 17:50:54 +02001426 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001427 if (*(args[arg+3])) {
1428 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001429 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001430 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001431 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434 }
1435
William Lallemand0f99e342011-10-12 17:50:54 +02001436 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001437 if (*(args[arg+4])) {
1438 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001439 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001440 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001441 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001442 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001443 }
1444 }
1445
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001446 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001447 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001448 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001449 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001450 free(logsrv);
1451 goto out;
1452 }
1453 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001454
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001455 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001456 if (port1 != port2) {
1457 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1458 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001459 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001460 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001461 goto out;
1462 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001463
William Lallemand0f99e342011-10-12 17:50:54 +02001464 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001465 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001466 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468
William Lallemand0f99e342011-10-12 17:50:54 +02001469 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001470 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001471 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1472 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001473
1474 if (global.log_send_hostname != NULL) {
1475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1476 err_code |= ERR_ALERT;
1477 goto out;
1478 }
1479
1480 if (*(args[1]))
1481 name = args[1];
1482 else
1483 name = hostname;
1484
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001485 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001486 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001487 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001488 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1489 if (global.server_state_base != NULL) {
1490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1491 err_code |= ERR_ALERT;
1492 goto out;
1493 }
1494
1495 if (!*(args[1])) {
1496 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1497 err_code |= ERR_FATAL;
1498 goto out;
1499 }
1500
1501 global.server_state_base = strdup(args[1]);
1502 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001503 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1504 if (global.server_state_file != NULL) {
1505 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1506 err_code |= ERR_ALERT;
1507 goto out;
1508 }
1509
1510 if (!*(args[1])) {
1511 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1512 err_code |= ERR_FATAL;
1513 goto out;
1514 }
1515
1516 global.server_state_file = strdup(args[1]);
1517 }
Kevinm48936af2010-12-22 16:08:21 +00001518 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001519 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1520 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001521 if (*(args[1]) == 0) {
1522 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
1525 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001526 chunk_destroy(&global.log_tag);
1527 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001528 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001529 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001530 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1531 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001532 if (global.spread_checks != 0) {
1533 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001534 err_code |= ERR_ALERT;
1535 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001536 }
1537 if (*(args[1]) == 0) {
1538 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001541 }
1542 global.spread_checks = atol(args[1]);
1543 if (global.spread_checks < 0 || global.spread_checks > 50) {
1544 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001547 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001548 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1549 const char *err;
1550 unsigned int val;
1551
William Lallemand1a748ae2015-05-19 16:37:23 +02001552 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1553 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001554 if (*(args[1]) == 0) {
1555 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
1558 }
1559
1560 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1561 if (err) {
1562 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1563 err_code |= ERR_ALERT | ERR_FATAL;
1564 }
1565 global.max_spread_checks = val;
1566 if (global.max_spread_checks < 0) {
1567 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1568 err_code |= ERR_ALERT | ERR_FATAL;
1569 }
1570 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001571 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1572#ifdef USE_CPU_AFFINITY
1573 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001574 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001575 unsigned long cpus = 0;
1576
1577 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001578 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001579 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001580 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001581 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001582 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001583 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001584 proc = atol(args[1]);
1585 if (proc >= 1 && proc <= LONGBITS)
1586 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001587 }
1588
1589 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001590 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1591 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001592 err_code |= ERR_ALERT | ERR_FATAL;
1593 goto out;
1594 }
1595
1596 cur_arg = 2;
1597 while (*args[cur_arg]) {
1598 unsigned int low, high;
1599
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001600 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001601 char *dash = strchr(args[cur_arg], '-');
1602
1603 low = high = str2uic(args[cur_arg]);
1604 if (dash)
1605 high = str2uic(dash + 1);
1606
1607 if (high < low) {
1608 unsigned int swap = low;
1609 low = high;
1610 high = swap;
1611 }
1612
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001613 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001614 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001615 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
1618 }
1619
1620 while (low <= high)
1621 cpus |= 1UL << low++;
1622 }
1623 else {
1624 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1625 file, linenum, args[0], args[cur_arg]);
1626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
1629 cur_arg++;
1630 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001631 for (i = 0; i < LONGBITS; i++)
1632 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001633 global.cpu_map[i] = cpus;
1634#else
1635 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
1638#endif
1639 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001640 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1641 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1642 goto out;
1643
1644 if (*(args[2]) == 0) {
1645 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1646 err_code |= ERR_ALERT | ERR_FATAL;
1647 goto out;
1648 }
1649
1650 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1651 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1652 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
1656 }
1657 else if (!strcmp(args[0], "unsetenv")) {
1658 int arg;
1659
1660 if (*(args[1]) == 0) {
1661 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
1664 }
1665
1666 for (arg = 1; *args[arg]; arg++) {
1667 if (unsetenv(args[arg]) != 0) {
1668 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1669 err_code |= ERR_ALERT | ERR_FATAL;
1670 goto out;
1671 }
1672 }
1673 }
1674 else if (!strcmp(args[0], "resetenv")) {
1675 extern char **environ;
1676 char **env = environ;
1677
1678 /* args contain variable names to keep, one per argument */
1679 while (*env) {
1680 int arg;
1681
1682 /* look for current variable in among all those we want to keep */
1683 for (arg = 1; *args[arg]; arg++) {
1684 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1685 (*env)[strlen(args[arg])] == '=')
1686 break;
1687 }
1688
1689 /* delete this variable */
1690 if (!*args[arg]) {
1691 char *delim = strchr(*env, '=');
1692
1693 if (!delim || delim - *env >= trash.size) {
1694 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
1698
1699 memcpy(trash.str, *env, delim - *env);
1700 trash.str[delim - *env] = 0;
1701
1702 if (unsetenv(trash.str) != 0) {
1703 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707 }
1708 else
1709 env++;
1710 }
1711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001713 struct cfg_kw_list *kwl;
1714 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001715 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001716
1717 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1718 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1719 if (kwl->kw[index].section != CFG_GLOBAL)
1720 continue;
1721 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001722 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001723 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001724 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001726 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001727 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001728 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001729 err_code |= ERR_WARN;
1730 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001731 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001732 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001733 }
1734 }
1735 }
1736
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001740
Willy Tarreau058e9072009-07-20 09:30:05 +02001741 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001742 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001743 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744}
1745
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001746void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001748 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749 defproxy.mode = PR_MODE_TCP;
1750 defproxy.state = PR_STNEW;
1751 defproxy.maxconn = cfg_maxpconn;
1752 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001753 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001754 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001755
Simon Horman66183002013-02-23 10:16:43 +09001756 defproxy.defsrv.check.inter = DEF_CHKINTR;
1757 defproxy.defsrv.check.fastinter = 0;
1758 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001759 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1760 defproxy.defsrv.agent.fastinter = 0;
1761 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001762 defproxy.defsrv.check.rise = DEF_RISETIME;
1763 defproxy.defsrv.check.fall = DEF_FALLTIME;
1764 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1765 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001766 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001767 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001768 defproxy.defsrv.maxqueue = 0;
1769 defproxy.defsrv.minconn = 0;
1770 defproxy.defsrv.maxconn = 0;
1771 defproxy.defsrv.slowstart = 0;
1772 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1773 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1774 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001775
1776 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001777 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778}
1779
Willy Tarreauade5ec42010-01-28 19:33:49 +01001780
Willy Tarreau63af98d2014-05-18 08:11:41 +02001781/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1782 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1783 * ERR_FATAL in case of error.
1784 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001785static int create_cond_regex_rule(const char *file, int line,
1786 struct proxy *px, int dir, int action, int flags,
1787 const char *cmd, const char *reg, const char *repl,
1788 const char **cond_start)
1789{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001790 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001791 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001792 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001793 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001794 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001795 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001796 int cs;
1797 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001798
1799 if (px == &defproxy) {
1800 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001801 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001802 goto err;
1803 }
1804
1805 if (*reg == 0) {
1806 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001807 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001808 goto err;
1809 }
1810
Christopher Faulet898566e2016-10-26 11:06:28 +02001811 if (warnifnotcap(px, PR_CAP_FE | PR_CAP_BE, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001812 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001813
Willy Tarreau5321c422010-01-28 20:35:13 +01001814 if (cond_start &&
1815 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001816 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1817 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1818 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001819 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001820 goto err;
1821 }
1822 }
1823 else if (cond_start && **cond_start) {
1824 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1825 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001826 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001827 goto err;
1828 }
1829
Willy Tarreau63af98d2014-05-18 08:11:41 +02001830 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001831 (dir == SMP_OPT_DIR_REQ) ?
1832 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1833 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1834 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001835
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001836 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001837 if (!preg) {
1838 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001839 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001840 goto err;
1841 }
1842
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001843 cs = !(flags & REG_ICASE);
1844 cap = !(flags & REG_NOSUB);
1845 error = NULL;
1846 if (!regex_comp(reg, preg, cs, cap, &error)) {
1847 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1848 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001849 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001850 goto err;
1851 }
1852
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001853 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001854 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001855 if (repl && err) {
1856 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1857 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001858 ret_code |= ERR_ALERT | ERR_FATAL;
1859 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001860 }
1861
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001862 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001863 ret_code |= ERR_WARN;
1864
1865 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001866
Willy Tarreau63af98d2014-05-18 08:11:41 +02001867 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001868 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001869 err:
1870 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001871 free(errmsg);
1872 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001873}
1874
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875/*
William Lallemand51097192015-04-14 16:35:22 +02001876 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001877 * Returns the error code, 0 if OK, or any combination of :
1878 * - ERR_ABORT: must abort ASAP
1879 * - ERR_FATAL: we can continue parsing but not start the service
1880 * - ERR_WARN: a warning has been emitted
1881 * - ERR_ALERT: an alert has been emitted
1882 * Only the two first ones can stop processing, the two others are just
1883 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001885int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1886{
1887 static struct peers *curpeers = NULL;
1888 struct peer *newpeer = NULL;
1889 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001890 struct bind_conf *bind_conf;
1891 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001892 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001893 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001894
1895 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001896 if (!*args[1]) {
1897 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001898 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001899 goto out;
1900 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001901
William Lallemand6e62fb62015-04-28 16:55:23 +02001902 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1903 goto out;
1904
Emeric Brun32da3c42010-09-23 18:39:19 +02001905 err = invalid_char(args[1]);
1906 if (err) {
1907 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1908 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001909 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001910 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 }
1912
1913 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1914 /*
1915 * If there are two proxies with the same name only following
1916 * combinations are allowed:
1917 */
1918 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001919 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001920 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 }
1923 }
1924
Vincent Bernat02779b62016-04-03 13:48:43 +02001925 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001926 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1927 err_code |= ERR_ALERT | ERR_ABORT;
1928 goto out;
1929 }
1930
1931 curpeers->next = peers;
1932 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001933 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001934 curpeers->conf.line = linenum;
1935 curpeers->last_change = now.tv_sec;
1936 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001937 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 }
1939 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001940 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001941 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001942 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001943
1944 if (!*args[2]) {
1945 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1946 file, linenum, args[0]);
1947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
1949 }
1950
1951 err = invalid_char(args[1]);
1952 if (err) {
1953 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1954 file, linenum, *err, args[1]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
Vincent Bernat02779b62016-04-03 13:48:43 +02001959 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001960 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1961 err_code |= ERR_ALERT | ERR_ABORT;
1962 goto out;
1963 }
1964
1965 /* the peers are linked backwards first */
1966 curpeers->count++;
1967 newpeer->next = curpeers->remote;
1968 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001969 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001970 newpeer->conf.line = linenum;
1971
1972 newpeer->last_change = now.tv_sec;
1973 newpeer->id = strdup(args[1]);
1974
Willy Tarreau48ef4c92017-01-06 18:32:38 +01001975 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001976 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001977 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001980 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001981
1982 proto = protocol_by_family(sk->ss_family);
1983 if (!proto || !proto->connect) {
1984 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1985 file, linenum, args[0], args[1]);
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001989
1990 if (port1 != port2) {
1991 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1992 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
1995 }
1996
Willy Tarreau2aa38802013-02-20 19:20:59 +01001997 if (!port1) {
1998 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1999 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
2002 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002003
Emeric Brun32da3c42010-09-23 18:39:19 +02002004 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002005 newpeer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002006 newpeer->xprt = xprt_get(XPRT_RAW);
Willy Tarreaud02394b2012-05-11 18:32:18 +02002007 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002008
Emeric Brun32da3c42010-09-23 18:39:19 +02002009 if (strcmp(newpeer->id, localpeer) == 0) {
2010 /* Current is local peer, it define a frontend */
2011 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002012 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002013
2014 if (!curpeers->peers_fe) {
2015 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2017 err_code |= ERR_ALERT | ERR_ABORT;
2018 goto out;
2019 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002020
Willy Tarreau237250c2011-07-29 01:49:03 +02002021 init_new_proxy(curpeers->peers_fe);
2022 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002023 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002024 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2025 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002026 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002027
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002028 bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW));
Willy Tarreau4348fad2012-09-20 16:48:07 +02002029
Willy Tarreau902636f2013-03-10 19:44:48 +01002030 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2031 if (errmsg && *errmsg) {
2032 indent_msg(&errmsg, 2);
2033 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002034 }
2035 else
2036 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2037 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 err_code |= ERR_FATAL;
2039 goto out;
2040 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002041
2042 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002043 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002044 l->maxconn = curpeers->peers_fe->maxconn;
2045 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002046 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002047 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002048 l->analysers |= curpeers->peers_fe->fe_req_ana;
2049 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002050 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2051 global.maxsock += l->maxconn;
2052 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002053 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002054 else {
2055 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2056 file, linenum, args[0], args[1],
2057 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2058 err_code |= ERR_FATAL;
2059 goto out;
2060 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002061 }
2062 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002063 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2064 curpeers->state = PR_STSTOPPED;
2065 }
2066 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2067 curpeers->state = PR_STNEW;
2068 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002069 else if (*args[0] != 0) {
2070 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002076 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002077 return err_code;
2078}
2079
Baptiste Assmann325137d2015-04-13 23:40:55 +02002080/*
2081 * Parse a <resolvers> section.
2082 * Returns the error code, 0 if OK, or any combination of :
2083 * - ERR_ABORT: must abort ASAP
2084 * - ERR_FATAL: we can continue parsing but not start the service
2085 * - ERR_WARN: a warning has been emitted
2086 * - ERR_ALERT: an alert has been emitted
2087 * Only the two first ones can stop processing, the two others are just
2088 * indicators.
2089 */
2090int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2091{
2092 static struct dns_resolvers *curr_resolvers = NULL;
2093 struct dns_nameserver *newnameserver = NULL;
2094 const char *err;
2095 int err_code = 0;
2096 char *errmsg = NULL;
2097
2098 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2099 if (!*args[1]) {
2100 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2101 err_code |= ERR_ALERT | ERR_ABORT;
2102 goto out;
2103 }
2104
2105 err = invalid_char(args[1]);
2106 if (err) {
2107 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2108 file, linenum, *err, args[0], args[1]);
2109 err_code |= ERR_ALERT | ERR_ABORT;
2110 goto out;
2111 }
2112
2113 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2114 /* Error if two resolvers owns the same name */
2115 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2116 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2117 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2118 err_code |= ERR_ALERT | ERR_ABORT;
2119 }
2120 }
2121
Vincent Bernat02779b62016-04-03 13:48:43 +02002122 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2124 err_code |= ERR_ALERT | ERR_ABORT;
2125 goto out;
2126 }
2127
2128 /* default values */
2129 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2130 curr_resolvers->conf.file = strdup(file);
2131 curr_resolvers->conf.line = linenum;
2132 curr_resolvers->id = strdup(args[1]);
2133 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002134 /* default hold period for nx, other, refuse and timeout is 30s */
2135 curr_resolvers->hold.nx = 30000;
2136 curr_resolvers->hold.other = 30000;
2137 curr_resolvers->hold.refused = 30000;
2138 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002139 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002140 curr_resolvers->hold.valid = 10000;
2141 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002142 curr_resolvers->resolve_retries = 3;
2143 LIST_INIT(&curr_resolvers->nameserver_list);
2144 LIST_INIT(&curr_resolvers->curr_resolution);
2145 }
2146 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2147 struct sockaddr_storage *sk;
2148 int port1, port2;
2149 struct protocol *proto;
2150
2151 if (!*args[2]) {
2152 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2153 file, linenum, args[0]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
2157
2158 err = invalid_char(args[1]);
2159 if (err) {
2160 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2161 file, linenum, *err, args[1]);
2162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
2164 }
2165
Baptiste Assmanna315c552015-11-02 22:55:49 +01002166 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2167 /* Error if two resolvers owns the same name */
2168 if (strcmp(newnameserver->id, args[1]) == 0) {
2169 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2170 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2171 err_code |= ERR_ALERT | ERR_FATAL;
2172 }
2173 }
2174
Vincent Bernat02779b62016-04-03 13:48:43 +02002175 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002176 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2177 err_code |= ERR_ALERT | ERR_ABORT;
2178 goto out;
2179 }
2180
2181 /* the nameservers are linked backward first */
2182 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2183 curr_resolvers->count_nameservers++;
2184 newnameserver->resolvers = curr_resolvers;
2185 newnameserver->conf.file = strdup(file);
2186 newnameserver->conf.line = linenum;
2187 newnameserver->id = strdup(args[1]);
2188
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002189 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002190 if (!sk) {
2191 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
2196 proto = protocol_by_family(sk->ss_family);
2197 if (!proto || !proto->connect) {
2198 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2199 file, linenum, args[0], args[1]);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
2204 if (port1 != port2) {
2205 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2206 file, linenum, args[0], args[1], args[2]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002211 if (!port1 && !port2) {
2212 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2213 file, linenum, args[0], args[1]);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
2216 }
2217
Baptiste Assmann325137d2015-04-13 23:40:55 +02002218 newnameserver->addr = *sk;
2219 }
2220 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2221 const char *res;
2222 unsigned int time;
2223
2224 if (!*args[2]) {
2225 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2226 file, linenum, args[0]);
2227 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2232 if (res) {
2233 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2234 file, linenum, *res, args[0]);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002238 if (strcmp(args[1], "nx") == 0)
2239 curr_resolvers->hold.nx = time;
2240 else if (strcmp(args[1], "other") == 0)
2241 curr_resolvers->hold.other = time;
2242 else if (strcmp(args[1], "refused") == 0)
2243 curr_resolvers->hold.refused = time;
2244 else if (strcmp(args[1], "timeout") == 0)
2245 curr_resolvers->hold.timeout = time;
2246 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002247 curr_resolvers->hold.valid = time;
2248 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002249 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2250 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
2253 }
2254
2255 }
2256 else if (strcmp(args[0], "resolve_retries") == 0) {
2257 if (!*args[1]) {
2258 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2259 file, linenum, args[0]);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263 curr_resolvers->resolve_retries = atoi(args[1]);
2264 }
2265 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002266 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002267 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2268 file, linenum, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002272 else if (strcmp(args[1], "retry") == 0) {
2273 const char *res;
2274 unsigned int timeout_retry;
2275
2276 if (!*args[2]) {
2277 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2278 file, linenum, args[0], args[1]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2283 if (res) {
2284 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2285 file, linenum, *res, args[0], args[1]);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289 curr_resolvers->timeout.retry = timeout_retry;
2290 }
2291 else {
2292 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2293 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002297 } /* neither "nameserver" nor "resolvers" */
2298 else if (*args[0] != 0) {
2299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
2303
2304 out:
2305 free(errmsg);
2306 return err_code;
2307}
Simon Horman0d16a402015-01-30 11:22:58 +09002308
2309/*
William Lallemand51097192015-04-14 16:35:22 +02002310 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002311 * Returns the error code, 0 if OK, or any combination of :
2312 * - ERR_ABORT: must abort ASAP
2313 * - ERR_FATAL: we can continue parsing but not start the service
2314 * - ERR_WARN: a warning has been emitted
2315 * - ERR_ALERT: an alert has been emitted
2316 * Only the two first ones can stop processing, the two others are just
2317 * indicators.
2318 */
2319int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2320{
2321 static struct mailers *curmailers = NULL;
2322 struct mailer *newmailer = NULL;
2323 const char *err;
2324 int err_code = 0;
2325 char *errmsg = NULL;
2326
2327 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2328 if (!*args[1]) {
2329 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2330 err_code |= ERR_ALERT | ERR_ABORT;
2331 goto out;
2332 }
2333
2334 err = invalid_char(args[1]);
2335 if (err) {
2336 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2337 file, linenum, *err, args[0], args[1]);
2338 err_code |= ERR_ALERT | ERR_ABORT;
2339 goto out;
2340 }
2341
2342 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2343 /*
2344 * If there are two proxies with the same name only following
2345 * combinations are allowed:
2346 */
2347 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002348 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002349 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002351 }
2352 }
2353
Vincent Bernat02779b62016-04-03 13:48:43 +02002354 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2356 err_code |= ERR_ALERT | ERR_ABORT;
2357 goto out;
2358 }
2359
2360 curmailers->next = mailers;
2361 mailers = curmailers;
2362 curmailers->conf.file = strdup(file);
2363 curmailers->conf.line = linenum;
2364 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002365 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2366 * But need enough time so that timeouts don't occur
2367 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002368 }
2369 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2370 struct sockaddr_storage *sk;
2371 int port1, port2;
2372 struct protocol *proto;
2373
2374 if (!*args[2]) {
2375 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2376 file, linenum, args[0]);
2377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
2379 }
2380
2381 err = invalid_char(args[1]);
2382 if (err) {
2383 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2384 file, linenum, *err, args[1]);
2385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
2387 }
2388
Vincent Bernat02779b62016-04-03 13:48:43 +02002389 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
2393 }
2394
2395 /* the mailers are linked backwards first */
2396 curmailers->count++;
2397 newmailer->next = curmailers->mailer_list;
2398 curmailers->mailer_list = newmailer;
2399 newmailer->mailers = curmailers;
2400 newmailer->conf.file = strdup(file);
2401 newmailer->conf.line = linenum;
2402
2403 newmailer->id = strdup(args[1]);
2404
Willy Tarreau48ef4c92017-01-06 18:32:38 +01002405 sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002406 if (!sk) {
2407 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
2410 }
2411
2412 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002413 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2414 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002415 file, linenum, args[0], args[1]);
2416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
2418 }
2419
2420 if (port1 != port2) {
2421 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2422 file, linenum, args[0], args[1], args[2]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 if (!port1) {
2428 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2429 file, linenum, args[0], args[1], args[2]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433
2434 newmailer->addr = *sk;
2435 newmailer->proto = proto;
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002436 newmailer->xprt = xprt_get(XPRT_RAW);
Simon Horman0d16a402015-01-30 11:22:58 +09002437 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002438 }
2439 else if (strcmp(args[0], "timeout") == 0) {
2440 if (!*args[1]) {
2441 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2442 file, linenum, args[0]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446 else if (strcmp(args[1], "mail") == 0) {
2447 const char *res;
2448 unsigned int timeout_mail;
2449 if (!*args[2]) {
2450 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2451 file, linenum, args[0], args[1]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2456 if (res) {
2457 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2458 file, linenum, *res, args[0]);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462 if (timeout_mail <= 0) {
2463 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467 curmailers->timeout.mail = timeout_mail;
2468 } else {
2469 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2470 file, linenum, args[0], args[1]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
2474 }
Simon Horman0d16a402015-01-30 11:22:58 +09002475 else if (*args[0] != 0) {
2476 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481out:
2482 free(errmsg);
2483 return err_code;
2484}
2485
Simon Horman9dc49962015-01-30 11:22:59 +09002486static void free_email_alert(struct proxy *p)
2487{
2488 free(p->email_alert.mailers.name);
2489 p->email_alert.mailers.name = NULL;
2490 free(p->email_alert.from);
2491 p->email_alert.from = NULL;
2492 free(p->email_alert.to);
2493 p->email_alert.to = NULL;
2494 free(p->email_alert.myhostname);
2495 p->email_alert.myhostname = NULL;
2496}
2497
Willy Tarreau3842f002009-06-14 11:39:52 +02002498int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499{
2500 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002501 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002502 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002503 int rc;
2504 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002505 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002506 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002507 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002508 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002509 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510
Willy Tarreau977b8e42006-12-29 14:19:17 +01002511 if (!strcmp(args[0], "listen"))
2512 rc = PR_CAP_LISTEN;
2513 else if (!strcmp(args[0], "frontend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002514 rc = PR_CAP_FE;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002515 else if (!strcmp(args[0], "backend"))
Christopher Faulet898566e2016-10-26 11:06:28 +02002516 rc = PR_CAP_BE;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002517 else
2518 rc = PR_CAP_NONE;
2519
2520 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 if (!*args[1]) {
2522 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002523 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_ABORT;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002528
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002529 err = invalid_char(args[1]);
2530 if (err) {
2531 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2532 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002534 }
2535
Willy Tarreau8f50b682015-05-26 11:45:02 +02002536 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2537 if (curproxy) {
2538 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2539 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2540 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002542 }
2543
Vincent Bernat02779b62016-04-03 13:48:43 +02002544 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_ABORT;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002549
Willy Tarreau97cb7802010-01-03 20:23:58 +01002550 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 curproxy->next = proxy;
2552 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002553 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2554 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002555 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002558 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559
William Lallemand6e62fb62015-04-28 16:55:23 +02002560 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2561 if (curproxy->cap & PR_CAP_FE)
2562 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565
2566 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002567 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002568 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002572 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002573 curproxy->no_options = defproxy.no_options;
2574 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002575 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002576 curproxy->except_net = defproxy.except_net;
2577 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002578 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002579 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002581 if (defproxy.fwdfor_hdr_len) {
2582 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2583 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2584 }
2585
Willy Tarreaub86db342009-11-30 11:50:16 +01002586 if (defproxy.orgto_hdr_len) {
2587 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2588 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2589 }
2590
Mark Lamourinec2247f02012-01-04 13:02:01 -05002591 if (defproxy.server_id_hdr_len) {
2592 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2593 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2594 }
2595
Willy Tarreau977b8e42006-12-29 14:19:17 +01002596 if (curproxy->cap & PR_CAP_FE) {
2597 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002598 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002599 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600
2601 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002602 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2603 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604
2605 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002609 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002610 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611 curproxy->fullconn = defproxy.fullconn;
2612 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002613 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002614 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002616 if (defproxy.check_req) {
2617 curproxy->check_req = calloc(1, defproxy.check_len);
2618 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2619 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002622 if (defproxy.expect_str) {
2623 curproxy->expect_str = strdup(defproxy.expect_str);
2624 if (defproxy.expect_regex) {
2625 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002626 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2627 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002628 }
2629 }
2630
Willy Tarreau67402132012-05-31 20:40:20 +02002631 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002632 if (defproxy.cookie_name)
2633 curproxy->cookie_name = strdup(defproxy.cookie_name);
2634 curproxy->cookie_len = defproxy.cookie_len;
Olivier Houchard4e694042017-03-14 20:01:29 +01002635
2636 if (defproxy.dyncookie_key)
2637 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002638 if (defproxy.cookie_domain)
2639 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002640
Willy Tarreau31936852010-10-06 16:59:56 +02002641 if (defproxy.cookie_maxidle)
2642 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2643
2644 if (defproxy.cookie_maxlife)
2645 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2646
Emeric Brun647caf12009-06-30 17:57:00 +02002647 if (defproxy.rdp_cookie_name)
2648 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2649 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2650
Willy Tarreau01732802007-11-01 22:48:15 +01002651 if (defproxy.url_param_name)
2652 curproxy->url_param_name = strdup(defproxy.url_param_name);
2653 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002654
Benoitaffb4812009-03-25 13:02:10 +01002655 if (defproxy.hh_name)
2656 curproxy->hh_name = strdup(defproxy.hh_name);
2657 curproxy->hh_len = defproxy.hh_len;
2658 curproxy->hh_match_domain = defproxy.hh_match_domain;
2659
Willy Tarreauef9a3602012-12-08 22:29:20 +01002660 if (defproxy.conn_src.iface_name)
2661 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2662 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002663 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002664#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002665 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002666#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002667 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002670 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671 if (defproxy.capture_name)
2672 curproxy->capture_name = strdup(defproxy.capture_name);
2673 curproxy->capture_namelen = defproxy.capture_namelen;
2674 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676
Willy Tarreau977b8e42006-12-29 14:19:17 +01002677 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002678 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002679 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002680 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002681 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002682 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683 curproxy->mon_net = defproxy.mon_net;
2684 curproxy->mon_mask = defproxy.mon_mask;
2685 if (defproxy.monitor_uri)
2686 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2687 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002688 if (defproxy.defbe.name)
2689 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002690
2691 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002692 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2693 if (curproxy->conf.logformat_string &&
2694 curproxy->conf.logformat_string != default_http_log_format &&
2695 curproxy->conf.logformat_string != default_tcp_log_format &&
2696 curproxy->conf.logformat_string != clf_http_log_format)
2697 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2698
2699 if (defproxy.conf.lfs_file) {
2700 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2701 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2702 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002703
2704 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2705 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2706 if (curproxy->conf.logformat_sd_string &&
2707 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2708 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2709
2710 if (defproxy.conf.lfsd_file) {
2711 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2712 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2713 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 }
2715
2716 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002717 curproxy->timeout.connect = defproxy.timeout.connect;
2718 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002719 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002720 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002721 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002722 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002723 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002724 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002725 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002726 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002727 }
2728
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002730 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002731
2732 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002733 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002734 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002735 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002736 LIST_INIT(&node->list);
2737 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2738 }
2739
Willy Tarreau62a61232013-04-12 18:13:46 +02002740 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2741 if (curproxy->conf.uniqueid_format_string)
2742 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2743
Dragan Dosen43885c72015-10-01 13:18:13 +02002744 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002745
Willy Tarreau62a61232013-04-12 18:13:46 +02002746 if (defproxy.conf.uif_file) {
2747 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2748 curproxy->conf.uif_line = defproxy.conf.uif_line;
2749 }
William Lallemanda73203e2012-03-12 12:48:57 +01002750
2751 /* copy default header unique id */
2752 if (defproxy.header_unique_id)
2753 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2754
William Lallemand82fe75c2012-10-23 10:25:10 +02002755 /* default compression options */
2756 if (defproxy.comp != NULL) {
2757 curproxy->comp = calloc(1, sizeof(struct comp));
2758 curproxy->comp->algos = defproxy.comp->algos;
2759 curproxy->comp->types = defproxy.comp->types;
2760 }
2761
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002763 curproxy->conf.used_listener_id = EB_ROOT;
2764 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002765
Simon Horman98637e52014-06-20 12:30:16 +09002766 if (defproxy.check_path)
2767 curproxy->check_path = strdup(defproxy.check_path);
2768 if (defproxy.check_command)
2769 curproxy->check_command = strdup(defproxy.check_command);
2770
Simon Horman9dc49962015-01-30 11:22:59 +09002771 if (defproxy.email_alert.mailers.name)
2772 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2773 if (defproxy.email_alert.from)
2774 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2775 if (defproxy.email_alert.to)
2776 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2777 if (defproxy.email_alert.myhostname)
2778 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002779 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002780 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002781
Willy Tarreau93893792009-07-23 13:19:11 +02002782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
2784 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2785 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002786 /* FIXME-20070101: we should do this too at the end of the
2787 * config parsing to free all default values.
2788 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002789 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2790 err_code |= ERR_ABORT;
2791 goto out;
2792 }
2793
Willy Tarreaua534fea2008-08-03 12:19:50 +02002794 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002795 free(defproxy.check_command);
2796 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002797 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002798 free(defproxy.rdp_cookie_name);
Olivier Houchard4e694042017-03-14 20:01:29 +01002799 free(defproxy.dyncookie_key);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002800 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002801 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002802 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002803 free(defproxy.capture_name);
2804 free(defproxy.monitor_uri);
2805 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002806 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002807 free(defproxy.fwdfor_hdr_name);
2808 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002809 free(defproxy.orgto_hdr_name);
2810 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002811 free(defproxy.server_id_hdr_name);
2812 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002813 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002814 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002815 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002816 free(defproxy.expect_regex);
2817 defproxy.expect_regex = NULL;
2818 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002819
Willy Tarreau62a61232013-04-12 18:13:46 +02002820 if (defproxy.conf.logformat_string != default_http_log_format &&
2821 defproxy.conf.logformat_string != default_tcp_log_format &&
2822 defproxy.conf.logformat_string != clf_http_log_format)
2823 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002824
Willy Tarreau62a61232013-04-12 18:13:46 +02002825 free(defproxy.conf.uniqueid_format_string);
2826 free(defproxy.conf.lfs_file);
2827 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002828 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002829 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002830
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002831 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2832 free(defproxy.conf.logformat_sd_string);
2833 free(defproxy.conf.lfsd_file);
2834
Willy Tarreaua534fea2008-08-03 12:19:50 +02002835 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002836 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002837
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 /* we cannot free uri_auth because it might already be used */
2839 init_default_instance();
2840 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002841 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2842 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002843 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 }
2846 else if (curproxy == NULL) {
2847 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002851
2852 /* update the current file and line being parsed */
2853 curproxy->conf.args.file = curproxy->conf.file;
2854 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002855
2856 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002857 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2858 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2859 if (err_code & ERR_FATAL)
2860 goto out;
2861 }
2862 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002863 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002864 int cur_arg;
2865
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 if (curproxy == &defproxy) {
2867 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002871 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873
Willy Tarreau24709282013-03-10 21:32:12 +01002874 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002875 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002880
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002881 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002882
2883 /* use default settings for unix sockets */
2884 bind_conf->ux.uid = global.unix_bind.ux.uid;
2885 bind_conf->ux.gid = global.unix_bind.ux.gid;
2886 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002887
2888 /* NOTE: the following line might create several listeners if there
2889 * are comma-separated IPs or port ranges. So all further processing
2890 * will have to be applied to all listeners created after last_listen.
2891 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002892 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2893 if (errmsg && *errmsg) {
2894 indent_msg(&errmsg, 2);
2895 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002896 }
2897 else
2898 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2899 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002903
Willy Tarreau4348fad2012-09-20 16:48:07 +02002904 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2905 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002906 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002907 }
2908
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002909 cur_arg = 2;
2910 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002911 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002912 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002913 char *err;
2914
Willy Tarreau26982662012-09-12 23:17:10 +02002915 kw = bind_find_kw(args[cur_arg]);
2916 if (kw) {
2917 char *err = NULL;
2918 int code;
2919
2920 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002921 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2922 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002923 cur_arg += 1 + kw->skip ;
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926 }
2927
Willy Tarreau4348fad2012-09-20 16:48:07 +02002928 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002929 err_code |= code;
2930
2931 if (code) {
2932 if (err && *err) {
2933 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002934 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002935 }
2936 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002937 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2938 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002939 if (code & ERR_FATAL) {
2940 free(err);
2941 cur_arg += 1 + kw->skip;
2942 goto out;
2943 }
2944 }
2945 free(err);
2946 cur_arg += 1 + kw->skip;
2947 continue;
2948 }
2949
Willy Tarreau8638f482012-09-18 18:01:17 +02002950 err = NULL;
2951 if (!bind_dumped) {
2952 bind_dump_kws(&err);
2953 indent_msg(&err, 4);
2954 bind_dumped = 1;
2955 }
2956
2957 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2958 file, linenum, args[0], args[1], args[cur_arg],
2959 err ? " Registered keywords :" : "", err ? err : "");
2960 free(err);
2961
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002964 }
Willy Tarreau93893792009-07-23 13:19:11 +02002965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002968 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2970 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 /* flush useless bits */
2978 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002981 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002982 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002983 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984
William Lallemanddf1425a2015-04-28 20:17:49 +02002985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2986 goto out;
2987
Willy Tarreau1c47f852006-07-09 08:22:27 +02002988 if (!*args[1]) {
2989 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2990 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002993 }
2994
Willy Tarreaua534fea2008-08-03 12:19:50 +02002995 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002996 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002997 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002998 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002999 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3000
Willy Tarreau93893792009-07-23 13:19:11 +02003001 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003004 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3005 goto out;
3006
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3008 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3009 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3010 else {
3011 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 }
3015 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003016 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003017 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003018
3019 if (curproxy == &defproxy) {
3020 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003024 }
3025
William Lallemanddf1425a2015-04-28 20:17:49 +02003026 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3027 goto out;
3028
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003029 if (!*args[1]) {
3030 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003034 }
3035
3036 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003037 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003038 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003039
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003040 if (curproxy->uuid <= 0) {
3041 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003042 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003045 }
3046
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003047 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3048 if (node) {
3049 struct proxy *target = container_of(node, struct proxy, conf.id);
3050 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3051 file, linenum, proxy_type_str(curproxy), curproxy->id,
3052 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003057 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003058 else if (!strcmp(args[0], "description")) {
3059 int i, len=0;
3060 char *d;
3061
Cyril Bonté99ed3272010-01-24 23:29:44 +01003062 if (curproxy == &defproxy) {
3063 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3064 file, linenum, args[0]);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
3068
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003069 if (!*args[1]) {
3070 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3071 file, linenum, args[0]);
3072 return -1;
3073 }
3074
Willy Tarreau348acfe2014-04-14 15:00:39 +02003075 for (i = 1; *args[i]; i++)
3076 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003077
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003078 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003079 curproxy->desc = d;
3080
Willy Tarreau348acfe2014-04-14 15:00:39 +02003081 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3082 for (i = 2; *args[i]; i++)
3083 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003084
3085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003087 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 curproxy->state = PR_STSTOPPED;
3090 }
3091 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003092 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 curproxy->state = PR_STNEW;
3095 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003096 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3097 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003098 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003099
3100 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003101 unsigned int low, high;
3102
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003103 if (strcmp(args[cur_arg], "all") == 0) {
3104 set = 0;
3105 break;
3106 }
3107 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003108 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003109 }
3110 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003111 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003112 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003113 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003114 char *dash = strchr(args[cur_arg], '-');
3115
3116 low = high = str2uic(args[cur_arg]);
3117 if (dash)
3118 high = str2uic(dash + 1);
3119
3120 if (high < low) {
3121 unsigned int swap = low;
3122 low = high;
3123 high = swap;
3124 }
3125
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003126 if (low < 1 || high > LONGBITS) {
3127 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3128 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003131 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003132 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003133 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003134 }
3135 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003136 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3137 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003140 }
3141 cur_arg++;
3142 }
3143 curproxy->bind_proc = set;
3144 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003145 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003146 if (curproxy == &defproxy) {
3147 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003150 }
3151
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003152 err = invalid_char(args[1]);
3153 if (err) {
3154 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3155 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003157 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003158 }
3159
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003160 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003161 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3162 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003165 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003166 }
3167 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3168
3169 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3170 err_code |= ERR_WARN;
3171
3172 if (*(args[1]) == 0) {
3173 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3174 file, linenum, args[0]);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
3178 free(curproxy->dyncookie_key);
3179 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3182 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183
Willy Tarreau977b8e42006-12-29 14:19:17 +01003184 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003185 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003186
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 if (*(args[1]) == 0) {
3188 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3189 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003193
Willy Tarreau67402132012-05-31 20:40:20 +02003194 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003195 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003196 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003197 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 curproxy->cookie_name = strdup(args[1]);
3199 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003200
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 cur_arg = 2;
3202 while (*(args[cur_arg])) {
3203 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003204 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 }
3206 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003207 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
3209 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003210 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 }
3212 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003213 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
3215 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003216 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003218 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003219 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003222 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003224 else if (!strcmp(args[cur_arg], "httponly")) {
3225 curproxy->ck_opts |= PR_CK_HTTPONLY;
3226 }
3227 else if (!strcmp(args[cur_arg], "secure")) {
3228 curproxy->ck_opts |= PR_CK_SECURE;
3229 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003230 else if (!strcmp(args[cur_arg], "domain")) {
3231 if (!*args[cur_arg + 1]) {
3232 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3233 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003236 }
3237
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003238 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003239 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003240 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3241 " dots nor does not start with a dot."
3242 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003243 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003244 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003245 }
3246
3247 err = invalid_domainchar(args[cur_arg + 1]);
3248 if (err) {
3249 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3250 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003253 }
3254
Willy Tarreau68a897b2009-12-03 23:28:34 +01003255 if (!curproxy->cookie_domain) {
3256 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3257 } else {
3258 /* one domain was already specified, add another one by
3259 * building the string which will be returned along with
3260 * the cookie.
3261 */
3262 char *new_ptr;
3263 int new_len = strlen(curproxy->cookie_domain) +
3264 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3265 new_ptr = malloc(new_len);
3266 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3267 free(curproxy->cookie_domain);
3268 curproxy->cookie_domain = new_ptr;
3269 }
Willy Tarreau31936852010-10-06 16:59:56 +02003270 cur_arg++;
3271 }
3272 else if (!strcmp(args[cur_arg], "maxidle")) {
3273 unsigned int maxidle;
3274 const char *res;
3275
3276 if (!*args[cur_arg + 1]) {
3277 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3278 file, linenum, args[cur_arg]);
3279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
3281 }
3282
3283 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3284 if (res) {
3285 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3286 file, linenum, *res, args[cur_arg]);
3287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
3289 }
3290 curproxy->cookie_maxidle = maxidle;
3291 cur_arg++;
3292 }
3293 else if (!strcmp(args[cur_arg], "maxlife")) {
3294 unsigned int maxlife;
3295 const char *res;
3296
3297 if (!*args[cur_arg + 1]) {
3298 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3299 file, linenum, args[cur_arg]);
3300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
3302 }
3303
3304 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3305 if (res) {
3306 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3307 file, linenum, *res, args[cur_arg]);
3308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
3310 }
3311 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003312 cur_arg++;
3313 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003314 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003315
3316 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3317 err_code |= ERR_WARN;
3318 curproxy->ck_opts |= PR_CK_DYNAMIC;
3319 }
3320
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003322 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
3327 cur_arg++;
3328 }
Willy Tarreau67402132012-05-31 20:40:20 +02003329 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3331 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
3334
Willy Tarreau67402132012-05-31 20:40:20 +02003335 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3337 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003340
Willy Tarreau67402132012-05-31 20:40:20 +02003341 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003342 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3343 file, linenum);
3344 err_code |= ERR_ALERT | ERR_FATAL;
3345 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003347 else if (!strcmp(args[0], "email-alert")) {
3348 if (*(args[1]) == 0) {
3349 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3350 file, linenum, args[0]);
3351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
3353 }
3354
3355 if (!strcmp(args[1], "from")) {
3356 if (*(args[1]) == 0) {
3357 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3358 file, linenum, args[1]);
3359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
3361 }
3362 free(curproxy->email_alert.from);
3363 curproxy->email_alert.from = strdup(args[2]);
3364 }
3365 else if (!strcmp(args[1], "mailers")) {
3366 if (*(args[1]) == 0) {
3367 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3368 file, linenum, args[1]);
3369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
3371 }
3372 free(curproxy->email_alert.mailers.name);
3373 curproxy->email_alert.mailers.name = strdup(args[2]);
3374 }
3375 else if (!strcmp(args[1], "myhostname")) {
3376 if (*(args[1]) == 0) {
3377 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3378 file, linenum, args[1]);
3379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
3381 }
3382 free(curproxy->email_alert.myhostname);
3383 curproxy->email_alert.myhostname = strdup(args[2]);
3384 }
Simon Horman64e34162015-02-06 11:11:57 +09003385 else if (!strcmp(args[1], "level")) {
3386 curproxy->email_alert.level = get_log_level(args[2]);
3387 if (curproxy->email_alert.level < 0) {
3388 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3389 file, linenum, args[1], args[2]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
3393 }
Simon Horman9dc49962015-01-30 11:22:59 +09003394 else if (!strcmp(args[1], "to")) {
3395 if (*(args[1]) == 0) {
3396 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3397 file, linenum, args[1]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401 free(curproxy->email_alert.to);
3402 curproxy->email_alert.to = strdup(args[2]);
3403 }
3404 else {
3405 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3406 file, linenum, args[1]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
Simon Horman64e34162015-02-06 11:11:57 +09003410 /* Indicate that the email_alert is at least partially configured */
3411 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003412 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003413 else if (!strcmp(args[0], "external-check")) {
3414 if (*(args[1]) == 0) {
3415 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3416 file, linenum, args[0]);
3417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
3419 }
3420
3421 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003422 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003423 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003424 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003425 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3426 file, linenum, args[1]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430 free(curproxy->check_command);
3431 curproxy->check_command = strdup(args[2]);
3432 }
3433 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003434 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003435 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003436 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003437 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3438 file, linenum, args[1]);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
3442 free(curproxy->check_path);
3443 curproxy->check_path = strdup(args[2]);
3444 }
3445 else {
3446 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3447 file, linenum, args[1]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
3451 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003452 else if (!strcmp(args[0], "persist")) { /* persist */
3453 if (*(args[1]) == 0) {
3454 Alert("parsing [%s:%d] : missing persist method.\n",
3455 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003458 }
3459
3460 if (!strncmp(args[1], "rdp-cookie", 10)) {
3461 curproxy->options2 |= PR_O2_RDPC_PRST;
3462
Emeric Brunb982a3d2010-01-04 15:45:53 +01003463 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003464 const char *beg, *end;
3465
3466 beg = args[1] + 11;
3467 end = strchr(beg, ')');
3468
William Lallemanddf1425a2015-04-28 20:17:49 +02003469 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3470 goto out;
3471
Emeric Brun647caf12009-06-30 17:57:00 +02003472 if (!end || end == beg) {
3473 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3474 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003477 }
3478
3479 free(curproxy->rdp_cookie_name);
3480 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3481 curproxy->rdp_cookie_len = end-beg;
3482 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003483 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003484 free(curproxy->rdp_cookie_name);
3485 curproxy->rdp_cookie_name = strdup("msts");
3486 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3487 }
3488 else { /* syntax */
3489 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3490 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003493 }
3494 }
3495 else {
3496 Alert("parsing [%s:%d] : unknown persist method.\n",
3497 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003500 }
3501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003503 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
3506 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003507 else if (!strcmp(args[0], "load-server-state-from-file")) {
3508 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3509 err_code |= ERR_WARN;
3510 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3511 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3512 }
3513 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3514 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3515 }
3516 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3517 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3518 }
3519 else {
3520 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3521 file, linenum, args[0], args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
3525 }
3526 else if (!strcmp(args[0], "server-state-file-name")) {
3527 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3528 err_code |= ERR_WARN;
3529 if (*(args[1]) == 0) {
3530 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3531 file, linenum, args[0]);
3532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
3534 }
3535 else if (!strcmp(args[1], "use-backend-name"))
3536 curproxy->server_state_file_name = strdup(curproxy->id);
3537 else
3538 curproxy->server_state_file_name = strdup(args[1]);
3539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003541 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003543
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003545 if (curproxy == &defproxy) {
3546 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
3549 }
3550
William Lallemand1a748ae2015-05-19 16:37:23 +02003551 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3552 goto out;
3553
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 if (*(args[4]) == 0) {
3555 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003560 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 curproxy->capture_name = strdup(args[2]);
3562 curproxy->capture_namelen = strlen(curproxy->capture_name);
3563 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 curproxy->to_log |= LW_COOKIE;
3565 }
3566 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3567 struct cap_hdr *hdr;
3568
3569 if (curproxy == &defproxy) {
3570 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 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 }
3574
William Lallemand1a748ae2015-05-19 16:37:23 +02003575 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3576 goto out;
3577
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3579 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3580 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 }
3584
Vincent Bernat02779b62016-04-03 13:48:43 +02003585 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 hdr->next = curproxy->req_cap;
3587 hdr->name = strdup(args[3]);
3588 hdr->namelen = strlen(args[3]);
3589 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003590 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 hdr->index = curproxy->nb_req_cap++;
3592 curproxy->req_cap = hdr;
3593 curproxy->to_log |= LW_REQHDR;
3594 }
3595 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3596 struct cap_hdr *hdr;
3597
3598 if (curproxy == &defproxy) {
3599 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 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 }
3603
William Lallemand1a748ae2015-05-19 16:37:23 +02003604 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3605 goto out;
3606
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3608 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3609 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003613 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 hdr->next = curproxy->rsp_cap;
3615 hdr->name = strdup(args[3]);
3616 hdr->namelen = strlen(args[3]);
3617 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003618 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 hdr->index = curproxy->nb_rsp_cap++;
3620 curproxy->rsp_cap = hdr;
3621 curproxy->to_log |= LW_RSPHDR;
3622 }
3623 else {
3624 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3625 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003626 err_code |= ERR_ALERT | ERR_FATAL;
3627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 }
3629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003633
William Lallemanddf1425a2015-04-28 20:17:49 +02003634 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3635 goto out;
3636
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 if (*(args[1]) == 0) {
3638 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3639 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
3643 curproxy->conn_retries = atol(args[1]);
3644 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003645 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003646 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003647
3648 if (curproxy == &defproxy) {
3649 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
3652 }
3653
Willy Tarreau20b0de52012-12-24 15:45:22 +01003654 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003655 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003656 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3657 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3658 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3659 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003660 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 +01003661 file, linenum, args[0]);
3662 err_code |= ERR_WARN;
3663 }
3664
Willy Tarreauff011f22011-01-06 17:51:27 +01003665 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003666
Willy Tarreauff011f22011-01-06 17:51:27 +01003667 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003668 err_code |= ERR_ALERT | ERR_ABORT;
3669 goto out;
3670 }
3671
Willy Tarreau5002f572014-04-23 01:32:02 +02003672 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003673 err_code |= warnif_cond_conflicts(rule->cond,
3674 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3675 file, linenum);
3676
Willy Tarreauff011f22011-01-06 17:51:27 +01003677 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003678 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003679 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003680 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003681
3682 if (curproxy == &defproxy) {
3683 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
3686 }
3687
3688 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003689 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003690 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3691 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003692 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3693 file, linenum, args[0]);
3694 err_code |= ERR_WARN;
3695 }
3696
3697 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3698
3699 if (!rule) {
3700 err_code |= ERR_ALERT | ERR_ABORT;
3701 goto out;
3702 }
3703
3704 err_code |= warnif_cond_conflicts(rule->cond,
3705 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3706 file, linenum);
3707
3708 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3709 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003710 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3711 /* set the header name and length into the proxy structure */
3712 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3713 err_code |= ERR_WARN;
3714
3715 if (!*args[1]) {
3716 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3717 file, linenum, args[0]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721
3722 /* set the desired header name */
3723 free(curproxy->server_id_hdr_name);
3724 curproxy->server_id_hdr_name = strdup(args[1]);
3725 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3726 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003727 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003728 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003729
Willy Tarreaub099aca2008-10-12 17:26:37 +02003730 if (curproxy == &defproxy) {
3731 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003734 }
3735
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003736 /* emulate "block" using "http-request block". Since these rules are supposed to
3737 * be processed before all http-request rules, we put them into their own list
3738 * and will insert them at the end.
3739 */
3740 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3741 if (!rule) {
3742 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003743 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003744 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003745 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3746 err_code |= warnif_cond_conflicts(rule->cond,
3747 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3748 file, linenum);
3749 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003750
3751 if (!already_warned(WARN_BLOCK_DEPRECATED))
3752 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]);
3753
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003754 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003755 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003756 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003757
Cyril Bonté99ed3272010-01-24 23:29:44 +01003758 if (curproxy == &defproxy) {
3759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
3762 }
3763
Willy Tarreaube4653b2015-05-28 15:26:58 +02003764 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003765 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3766 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003769 }
3770
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003771 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003772 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003773 err_code |= warnif_cond_conflicts(rule->cond,
3774 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3775 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003776 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003777 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003778 struct switching_rule *rule;
3779
Willy Tarreaub099aca2008-10-12 17:26:37 +02003780 if (curproxy == &defproxy) {
3781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003784 }
3785
Willy Tarreau55ea7572007-06-17 19:56:27 +02003786 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003788
3789 if (*(args[1]) == 0) {
3790 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003793 }
3794
Willy Tarreauf51658d2014-04-23 01:21:56 +02003795 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3796 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3797 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3798 file, linenum, errmsg);
3799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
3801 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003802
Willy Tarreauf51658d2014-04-23 01:21:56 +02003803 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003804 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003805 else if (*args[2]) {
3806 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3807 file, linenum, args[2]);
3808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
3810 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003811
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003812 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003813 if (!rule) {
3814 Alert("Out of memory error.\n");
3815 goto out;
3816 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003817 rule->cond = cond;
3818 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003819 rule->line = linenum;
3820 rule->file = strdup(file);
3821 if (!rule->file) {
3822 Alert("Out of memory error.\n");
3823 goto out;
3824 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003825 LIST_INIT(&rule->list);
3826 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3827 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003828 else if (strcmp(args[0], "use-server") == 0) {
3829 struct server_rule *rule;
3830
3831 if (curproxy == &defproxy) {
3832 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
3835 }
3836
3837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3838 err_code |= ERR_WARN;
3839
3840 if (*(args[1]) == 0) {
3841 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
3844 }
3845
3846 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3847 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3848 file, linenum, args[0]);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003853 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3854 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3855 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003860 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003861
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003862 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003863 rule->cond = cond;
3864 rule->srv.name = strdup(args[1]);
3865 LIST_INIT(&rule->list);
3866 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3867 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3868 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003869 else if ((!strcmp(args[0], "force-persist")) ||
3870 (!strcmp(args[0], "ignore-persist"))) {
3871 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003872
3873 if (curproxy == &defproxy) {
3874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878
3879 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3880 err_code |= ERR_WARN;
3881
Willy Tarreauef6494c2010-01-28 17:12:36 +01003882 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003883 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3884 file, linenum, args[0]);
3885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
3887 }
3888
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003889 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3890 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3891 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003896 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3897 * where force-persist is applied.
3898 */
3899 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003900
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003901 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003902 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003903 if (!strcmp(args[0], "force-persist")) {
3904 rule->type = PERSIST_TYPE_FORCE;
3905 } else {
3906 rule->type = PERSIST_TYPE_IGNORE;
3907 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003908 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003909 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003910 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003911 else if (!strcmp(args[0], "stick-table")) {
3912 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003913 struct proxy *other;
3914
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003915 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003916 if (other) {
3917 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3918 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003922
Emeric Brun32da3c42010-09-23 18:39:19 +02003923 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003924 curproxy->table.type = (unsigned int)-1;
3925 while (*args[myidx]) {
3926 const char *err;
3927
3928 if (strcmp(args[myidx], "size") == 0) {
3929 myidx++;
3930 if (!*(args[myidx])) {
3931 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3932 file, linenum, args[myidx-1]);
3933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
3935 }
3936 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3937 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3938 file, linenum, *err, args[myidx-1]);
3939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
3941 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003942 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003943 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003944 else if (strcmp(args[myidx], "peers") == 0) {
3945 myidx++;
Godbach50523162013-12-11 19:48:57 +08003946 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003947 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3948 file, linenum, args[myidx-1]);
3949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Godbach50523162013-12-11 19:48:57 +08003951 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003952 curproxy->table.peers.name = strdup(args[myidx++]);
3953 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003954 else if (strcmp(args[myidx], "expire") == 0) {
3955 myidx++;
3956 if (!*(args[myidx])) {
3957 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3958 file, linenum, args[myidx-1]);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3963 if (err) {
3964 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3965 file, linenum, *err, args[myidx-1]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003969 if (val > INT_MAX) {
3970 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3971 file, linenum, val);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003975 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003976 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003977 }
3978 else if (strcmp(args[myidx], "nopurge") == 0) {
3979 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003980 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003981 }
3982 else if (strcmp(args[myidx], "type") == 0) {
3983 myidx++;
3984 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3985 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3986 file, linenum, args[myidx]);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003990 /* myidx already points to next arg */
3991 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003992 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003993 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003994 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003995
3996 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003997 nw = args[myidx];
3998 while (*nw) {
3999 /* the "store" keyword supports a comma-separated list */
4000 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004001 sa = NULL; /* store arg */
4002 while (*nw && *nw != ',') {
4003 if (*nw == '(') {
4004 *nw = 0;
4005 sa = ++nw;
4006 while (*nw != ')') {
4007 if (!*nw) {
4008 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4009 file, linenum, args[0], cw);
4010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
4012 }
4013 nw++;
4014 }
4015 *nw = '\0';
4016 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004017 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004018 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004019 if (*nw)
4020 *nw++ = '\0';
4021 type = stktable_get_data_type(cw);
4022 if (type < 0) {
4023 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4024 file, linenum, args[0], cw);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
Willy Tarreauac782882010-06-20 10:41:54 +02004028
4029 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4030 switch (err) {
4031 case PE_NONE: break;
4032 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004033 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4034 file, linenum, args[0], cw);
4035 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004036 break;
4037
4038 case PE_ARG_MISSING:
4039 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4040 file, linenum, args[0], cw);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043
4044 case PE_ARG_NOT_USED:
4045 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4046 file, linenum, args[0], cw);
4047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
4049
4050 default:
4051 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4052 file, linenum, args[0], cw);
4053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004055 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004056 }
4057 myidx++;
4058 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004059 else {
4060 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4061 file, linenum, args[myidx]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004064 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004065 }
4066
4067 if (!curproxy->table.size) {
4068 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4069 file, linenum);
4070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
4072 }
4073
4074 if (curproxy->table.type == (unsigned int)-1) {
4075 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4076 file, linenum);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080 }
4081 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004082 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004083 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004084 int myidx = 0;
4085 const char *name = NULL;
4086 int flags;
4087
4088 if (curproxy == &defproxy) {
4089 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093
4094 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4095 err_code |= ERR_WARN;
4096 goto out;
4097 }
4098
4099 myidx++;
4100 if ((strcmp(args[myidx], "store") == 0) ||
4101 (strcmp(args[myidx], "store-request") == 0)) {
4102 myidx++;
4103 flags = STK_IS_STORE;
4104 }
4105 else if (strcmp(args[myidx], "store-response") == 0) {
4106 myidx++;
4107 flags = STK_IS_STORE | STK_ON_RSP;
4108 }
4109 else if (strcmp(args[myidx], "match") == 0) {
4110 myidx++;
4111 flags = STK_IS_MATCH;
4112 }
4113 else if (strcmp(args[myidx], "on") == 0) {
4114 myidx++;
4115 flags = STK_IS_MATCH | STK_IS_STORE;
4116 }
4117 else {
4118 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4119 err_code |= ERR_ALERT | ERR_FATAL;
4120 goto out;
4121 }
4122
4123 if (*(args[myidx]) == 0) {
4124 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004129 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004130 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004131 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004132 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136
4137 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004138 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4139 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4140 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004141 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004142 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004143 goto out;
4144 }
4145 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004146 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4147 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4148 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004149 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004150 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004151 goto out;
4152 }
4153 }
4154
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004155 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004156 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004157
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 if (strcmp(args[myidx], "table") == 0) {
4159 myidx++;
4160 name = args[myidx++];
4161 }
4162
Willy Tarreauef6494c2010-01-28 17:12:36 +01004163 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004164 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4165 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4166 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004167 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004168 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004169 goto out;
4170 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004171 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004172 else if (*(args[myidx])) {
4173 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4174 file, linenum, args[0], args[myidx]);
4175 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004176 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004177 goto out;
4178 }
Emeric Brun97679e72010-09-23 17:56:44 +02004179 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004180 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004181 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004182 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004183
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004184 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004185 rule->cond = cond;
4186 rule->expr = expr;
4187 rule->flags = flags;
4188 rule->table.name = name ? strdup(name) : NULL;
4189 LIST_INIT(&rule->list);
4190 if (flags & STK_ON_RSP)
4191 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4192 else
4193 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 else if (!strcmp(args[0], "stats")) {
4196 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4197 curproxy->uri_auth = NULL; /* we must detach from the default config */
4198
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004199 if (!*args[1]) {
4200 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004201 } else if (!strcmp(args[1], "admin")) {
4202 struct stats_admin_rule *rule;
4203
4204 if (curproxy == &defproxy) {
4205 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
4208 }
4209
4210 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4211 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4212 err_code |= ERR_ALERT | ERR_ABORT;
4213 goto out;
4214 }
4215
4216 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4217 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4218 file, linenum, args[0], args[1]);
4219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
4221 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004222 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4223 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4224 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
4227 }
4228
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004229 err_code |= warnif_cond_conflicts(cond,
4230 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4231 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004232
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004233 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004234 rule->cond = cond;
4235 LIST_INIT(&rule->list);
4236 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004237 } else if (!strcmp(args[1], "uri")) {
4238 if (*(args[2]) == 0) {
4239 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4243 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_ALERT | ERR_ABORT;
4245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 }
4247 } else if (!strcmp(args[1], "realm")) {
4248 if (*(args[2]) == 0) {
4249 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4253 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004254 err_code |= ERR_ALERT | ERR_ABORT;
4255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004256 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004257 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004258 unsigned interval;
4259
4260 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4261 if (err) {
4262 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4263 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004266 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4267 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004268 err_code |= ERR_ALERT | ERR_ABORT;
4269 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004270 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004271 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004272 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004273
4274 if (curproxy == &defproxy) {
4275 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
4280 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4281 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4282 err_code |= ERR_ALERT | ERR_ABORT;
4283 goto out;
4284 }
4285
Willy Tarreauff011f22011-01-06 17:51:27 +01004286 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004287 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004288 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4289 file, linenum, args[0]);
4290 err_code |= ERR_WARN;
4291 }
4292
Willy Tarreauff011f22011-01-06 17:51:27 +01004293 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004294
Willy Tarreauff011f22011-01-06 17:51:27 +01004295 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004296 err_code |= ERR_ALERT | ERR_ABORT;
4297 goto out;
4298 }
4299
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004300 err_code |= warnif_cond_conflicts(rule->cond,
4301 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4302 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004303 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004304
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 } else if (!strcmp(args[1], "auth")) {
4306 if (*(args[2]) == 0) {
4307 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004312 err_code |= ERR_ALERT | ERR_ABORT;
4313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 }
4315 } else if (!strcmp(args[1], "scope")) {
4316 if (*(args[2]) == 0) {
4317 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4321 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004322 err_code |= ERR_ALERT | ERR_ABORT;
4323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 }
4325 } else if (!strcmp(args[1], "enable")) {
4326 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_ABORT;
4329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004331 } else if (!strcmp(args[1], "hide-version")) {
4332 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4333 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_ALERT | ERR_ABORT;
4335 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004336 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004337 } else if (!strcmp(args[1], "show-legends")) {
4338 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4339 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4340 err_code |= ERR_ALERT | ERR_ABORT;
4341 goto out;
4342 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004343 } else if (!strcmp(args[1], "show-node")) {
4344
4345 if (*args[2]) {
4346 int i;
4347 char c;
4348
4349 for (i=0; args[2][i]; i++) {
4350 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004351 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4352 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004353 break;
4354 }
4355
4356 if (!i || args[2][i]) {
4357 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4358 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4359 file, linenum, args[0], args[1]);
4360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
4363 }
4364
4365 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4366 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4367 err_code |= ERR_ALERT | ERR_ABORT;
4368 goto out;
4369 }
4370 } else if (!strcmp(args[1], "show-desc")) {
4371 char *desc = NULL;
4372
4373 if (*args[2]) {
4374 int i, len=0;
4375 char *d;
4376
Willy Tarreau348acfe2014-04-14 15:00:39 +02004377 for (i = 2; *args[i]; i++)
4378 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004379
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004380 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004381
Willy Tarreau348acfe2014-04-14 15:00:39 +02004382 d += snprintf(d, desc + len - d, "%s", args[2]);
4383 for (i = 3; *args[i]; i++)
4384 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004385 }
4386
4387 if (!*args[2] && !global.desc)
4388 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4389 file, linenum, args[1]);
4390 else {
4391 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4392 free(desc);
4393 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4394 err_code |= ERR_ALERT | ERR_ABORT;
4395 goto out;
4396 }
4397 free(desc);
4398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004400stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004401 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 +01004402 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 }
4406 }
4407 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004408 int optnum;
4409
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004410 if (*(args[1]) == '\0') {
4411 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4412 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004416
4417 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4418 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004419 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4420 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4421 file, linenum, cfg_opts[optnum].name);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004425 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4426 goto out;
4427
Willy Tarreau93893792009-07-23 13:19:11 +02004428 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4429 err_code |= ERR_WARN;
4430 goto out;
4431 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004432
Willy Tarreau3842f002009-06-14 11:39:52 +02004433 curproxy->no_options &= ~cfg_opts[optnum].val;
4434 curproxy->options &= ~cfg_opts[optnum].val;
4435
4436 switch (kwm) {
4437 case KWM_STD:
4438 curproxy->options |= cfg_opts[optnum].val;
4439 break;
4440 case KWM_NO:
4441 curproxy->no_options |= cfg_opts[optnum].val;
4442 break;
4443 case KWM_DEF: /* already cleared */
4444 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004445 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004446
Willy Tarreau93893792009-07-23 13:19:11 +02004447 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004448 }
4449 }
4450
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004451 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4452 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004453 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4454 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4455 file, linenum, cfg_opts2[optnum].name);
4456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
4458 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004459 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4460 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004461 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4462 err_code |= ERR_WARN;
4463 goto out;
4464 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004465
Willy Tarreau3842f002009-06-14 11:39:52 +02004466 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4467 curproxy->options2 &= ~cfg_opts2[optnum].val;
4468
4469 switch (kwm) {
4470 case KWM_STD:
4471 curproxy->options2 |= cfg_opts2[optnum].val;
4472 break;
4473 case KWM_NO:
4474 curproxy->no_options2 |= cfg_opts2[optnum].val;
4475 break;
4476 case KWM_DEF: /* already cleared */
4477 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004478 }
Willy Tarreau93893792009-07-23 13:19:11 +02004479 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004480 }
4481 }
4482
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004483 /* HTTP options override each other. They can be cancelled using
4484 * "no option xxx" which only switches to default mode if the mode
4485 * was this one (useful for cancelling options set in defaults
4486 * sections).
4487 */
4488 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004489 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4490 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004491 if (kwm == KWM_STD) {
4492 curproxy->options &= ~PR_O_HTTP_MODE;
4493 curproxy->options |= PR_O_HTTP_PCL;
4494 goto out;
4495 }
4496 else if (kwm == KWM_NO) {
4497 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4498 curproxy->options &= ~PR_O_HTTP_MODE;
4499 goto out;
4500 }
4501 }
4502 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004503 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4504 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004505 if (kwm == KWM_STD) {
4506 curproxy->options &= ~PR_O_HTTP_MODE;
4507 curproxy->options |= PR_O_HTTP_FCL;
4508 goto out;
4509 }
4510 else if (kwm == KWM_NO) {
4511 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4512 curproxy->options &= ~PR_O_HTTP_MODE;
4513 goto out;
4514 }
4515 }
4516 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004517 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4518 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004519 if (kwm == KWM_STD) {
4520 curproxy->options &= ~PR_O_HTTP_MODE;
4521 curproxy->options |= PR_O_HTTP_SCL;
4522 goto out;
4523 }
4524 else if (kwm == KWM_NO) {
4525 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4526 curproxy->options &= ~PR_O_HTTP_MODE;
4527 goto out;
4528 }
4529 }
4530 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004531 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4532 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004533 if (kwm == KWM_STD) {
4534 curproxy->options &= ~PR_O_HTTP_MODE;
4535 curproxy->options |= PR_O_HTTP_KAL;
4536 goto out;
4537 }
4538 else if (kwm == KWM_NO) {
4539 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4540 curproxy->options &= ~PR_O_HTTP_MODE;
4541 goto out;
4542 }
4543 }
4544 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004545 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4546 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004547 if (kwm == KWM_STD) {
4548 curproxy->options &= ~PR_O_HTTP_MODE;
4549 curproxy->options |= PR_O_HTTP_TUN;
4550 goto out;
4551 }
4552 else if (kwm == KWM_NO) {
4553 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4554 curproxy->options &= ~PR_O_HTTP_MODE;
4555 goto out;
4556 }
4557 }
4558
Joseph Lynch726ab712015-05-11 23:25:34 -07004559 /* Redispatch can take an integer argument that control when the
4560 * resispatch occurs. All values are relative to the retries option.
4561 * This can be cancelled using "no option xxx".
4562 */
4563 if (strcmp(args[1], "redispatch") == 0) {
4564 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4565 err_code |= ERR_WARN;
4566 goto out;
4567 }
4568
4569 curproxy->no_options &= ~PR_O_REDISP;
4570 curproxy->options &= ~PR_O_REDISP;
4571
4572 switch (kwm) {
4573 case KWM_STD:
4574 curproxy->options |= PR_O_REDISP;
4575 curproxy->redispatch_after = -1;
4576 if(*args[2]) {
4577 curproxy->redispatch_after = atol(args[2]);
4578 }
4579 break;
4580 case KWM_NO:
4581 curproxy->no_options |= PR_O_REDISP;
4582 curproxy->redispatch_after = 0;
4583 break;
4584 case KWM_DEF: /* already cleared */
4585 break;
4586 }
4587 goto out;
4588 }
4589
Willy Tarreau3842f002009-06-14 11:39:52 +02004590 if (kwm != KWM_STD) {
4591 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004592 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004595 }
4596
Emeric Brun3a058f32009-06-30 18:26:00 +02004597 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004598 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004599 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004600 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004601 if (*(args[2]) != '\0') {
4602 if (!strcmp(args[2], "clf")) {
4603 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004604 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004605 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004606 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004609 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004610 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4611 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004612 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004613 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4614 char *oldlogformat = "log-format";
4615 char *clflogformat = "";
4616
4617 if (curproxy->conf.logformat_string == default_http_log_format)
4618 oldlogformat = "option httplog";
4619 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4620 oldlogformat = "option tcplog";
4621 else if (curproxy->conf.logformat_string == clf_http_log_format)
4622 oldlogformat = "option httplog clf";
4623 if (logformat == clf_http_log_format)
4624 clflogformat = " clf";
4625 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4626 file, linenum, clflogformat, oldlogformat);
4627 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004628 if (curproxy->conf.logformat_string != default_http_log_format &&
4629 curproxy->conf.logformat_string != default_tcp_log_format &&
4630 curproxy->conf.logformat_string != clf_http_log_format)
4631 free(curproxy->conf.logformat_string);
4632 curproxy->conf.logformat_string = logformat;
4633
4634 free(curproxy->conf.lfs_file);
4635 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4636 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004637 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004638 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004639 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4640 char *oldlogformat = "log-format";
4641
4642 if (curproxy->conf.logformat_string == default_http_log_format)
4643 oldlogformat = "option httplog";
4644 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4645 oldlogformat = "option tcplog";
4646 else if (curproxy->conf.logformat_string == clf_http_log_format)
4647 oldlogformat = "option httplog clf";
4648 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4649 file, linenum, oldlogformat);
4650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004652 if (curproxy->conf.logformat_string != default_http_log_format &&
4653 curproxy->conf.logformat_string != default_tcp_log_format &&
4654 curproxy->conf.logformat_string != clf_http_log_format)
4655 free(curproxy->conf.logformat_string);
4656 curproxy->conf.logformat_string = default_tcp_log_format;
4657
4658 free(curproxy->conf.lfs_file);
4659 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4660 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004661
4662 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4663 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004666 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004667 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004668 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004669
William Lallemanddf1425a2015-04-28 20:17:49 +02004670 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4671 goto out;
4672
Willy Tarreau13943ab2006-12-31 00:24:10 +01004673 if (curproxy->cap & PR_CAP_FE)
4674 curproxy->options |= PR_O_TCP_CLI_KA;
4675 if (curproxy->cap & PR_CAP_BE)
4676 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 }
4678 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004679 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004680 err_code |= ERR_WARN;
4681
Willy Tarreaubaaee002006-06-26 02:48:02 +02004682 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004683 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004684 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004685 curproxy->options2 &= ~PR_O2_CHK_ANY;
4686 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 if (!*args[2]) { /* no argument */
4688 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4689 curproxy->check_len = strlen(DEF_CHECK_REQ);
4690 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004691 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004692 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004694 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004696 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 if (*args[4])
4698 reqlen += strlen(args[4]);
4699 else
4700 reqlen += strlen("HTTP/1.0");
4701
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004702 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004704 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004706 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4707 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004708 }
4709 else if (!strcmp(args[1], "ssl-hello-chk")) {
4710 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004712 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004713
Willy Tarreaua534fea2008-08-03 12:19:50 +02004714 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004715 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004716 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004717 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004718
4719 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 }
Willy Tarreau23677902007-05-08 23:50:35 +02004722 else if (!strcmp(args[1], "smtpchk")) {
4723 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004724 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004725 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004726 curproxy->options2 &= ~PR_O2_CHK_ANY;
4727 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004728
4729 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4730 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4731 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4732 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4733 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4734 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004735 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004736 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4737 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4738 } else {
4739 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4740 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4741 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4742 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4743 }
4744 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004745 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4746 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004747 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004748 else if (!strcmp(args[1], "pgsql-check")) {
4749 /* use PostgreSQL request to check servers' health */
4750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4751 err_code |= ERR_WARN;
4752
4753 free(curproxy->check_req);
4754 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004755 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004756 curproxy->options2 |= PR_O2_PGSQL_CHK;
4757
4758 if (*(args[2])) {
4759 int cur_arg = 2;
4760
4761 while (*(args[cur_arg])) {
4762 if (strcmp(args[cur_arg], "user") == 0) {
4763 char * packet;
4764 uint32_t packet_len;
4765 uint32_t pv;
4766
4767 /* suboption header - needs additional argument for it */
4768 if (*(args[cur_arg+1]) == 0) {
4769 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4770 file, linenum, args[0], args[1], args[cur_arg]);
4771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
4773 }
4774
4775 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4776 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4777 pv = htonl(0x30000); /* protocol version 3.0 */
4778
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004779 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004780
4781 memcpy(packet + 4, &pv, 4);
4782
4783 /* copy "user" */
4784 memcpy(packet + 8, "user", 4);
4785
4786 /* copy username */
4787 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4788
4789 free(curproxy->check_req);
4790 curproxy->check_req = packet;
4791 curproxy->check_len = packet_len;
4792
4793 packet_len = htonl(packet_len);
4794 memcpy(packet, &packet_len, 4);
4795 cur_arg += 2;
4796 } else {
4797 /* unknown suboption - catchall */
4798 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4799 file, linenum, args[0], args[1]);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
4803 } /* end while loop */
4804 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004805 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4806 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004807 }
4808
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004809 else if (!strcmp(args[1], "redis-check")) {
4810 /* use REDIS PING request to check servers' health */
4811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4812 err_code |= ERR_WARN;
4813
4814 free(curproxy->check_req);
4815 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004816 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004817 curproxy->options2 |= PR_O2_REDIS_CHK;
4818
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004819 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004820 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4821 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004822
4823 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4824 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004825 }
4826
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004827 else if (!strcmp(args[1], "mysql-check")) {
4828 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004829 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4830 err_code |= ERR_WARN;
4831
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004832 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004833 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004834 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004835 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004836
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004837 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004838 * const char mysql40_client_auth_pkt[] = {
4839 * "\x0e\x00\x00" // packet length
4840 * "\x01" // packet number
4841 * "\x00\x00" // client capabilities
4842 * "\x00\x00\x01" // max packet
4843 * "haproxy\x00" // username (null terminated string)
4844 * "\x00" // filler (always 0x00)
4845 * "\x01\x00\x00" // packet length
4846 * "\x00" // packet number
4847 * "\x01" // COM_QUIT command
4848 * };
4849 */
4850
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004851 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4852 * const char mysql41_client_auth_pkt[] = {
4853 * "\x0e\x00\x00\" // packet length
4854 * "\x01" // packet number
4855 * "\x00\x00\x00\x00" // client capabilities
4856 * "\x00\x00\x00\x01" // max packet
4857 * "\x21" // character set (UTF-8)
4858 * char[23] // All zeroes
4859 * "haproxy\x00" // username (null terminated string)
4860 * "\x00" // filler (always 0x00)
4861 * "\x01\x00\x00" // packet length
4862 * "\x00" // packet number
4863 * "\x01" // COM_QUIT command
4864 * };
4865 */
4866
4867
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004868 if (*(args[2])) {
4869 int cur_arg = 2;
4870
4871 while (*(args[cur_arg])) {
4872 if (strcmp(args[cur_arg], "user") == 0) {
4873 char *mysqluser;
4874 int packetlen, reqlen, userlen;
4875
4876 /* suboption header - needs additional argument for it */
4877 if (*(args[cur_arg+1]) == 0) {
4878 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4879 file, linenum, args[0], args[1], args[cur_arg]);
4880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
4882 }
4883 mysqluser = args[cur_arg + 1];
4884 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004885
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004886 if (*(args[cur_arg+2])) {
4887 if (!strcmp(args[cur_arg+2], "post-41")) {
4888 packetlen = userlen + 7 + 27;
4889 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004890
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004891 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004892 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004893 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004894
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004895 snprintf(curproxy->check_req, 4, "%c%c%c",
4896 ((unsigned char) packetlen & 0xff),
4897 ((unsigned char) (packetlen >> 8) & 0xff),
4898 ((unsigned char) (packetlen >> 16) & 0xff));
4899
4900 curproxy->check_req[3] = 1;
4901 curproxy->check_req[5] = 130;
4902 curproxy->check_req[11] = 1;
4903 curproxy->check_req[12] = 33;
4904 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4905 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4906 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4907 cur_arg += 3;
4908 } else {
4909 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
4912 }
4913 } else {
4914 packetlen = userlen + 7;
4915 reqlen = packetlen + 9;
4916
4917 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004918 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004919 curproxy->check_len = reqlen;
4920
4921 snprintf(curproxy->check_req, 4, "%c%c%c",
4922 ((unsigned char) packetlen & 0xff),
4923 ((unsigned char) (packetlen >> 8) & 0xff),
4924 ((unsigned char) (packetlen >> 16) & 0xff));
4925
4926 curproxy->check_req[3] = 1;
4927 curproxy->check_req[5] = 128;
4928 curproxy->check_req[8] = 1;
4929 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4930 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4931 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4932 cur_arg += 2;
4933 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004934 } else {
4935 /* unknown suboption - catchall */
4936 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4937 file, linenum, args[0], args[1]);
4938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
4940 }
4941 } /* end while loop */
4942 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004943 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004944 else if (!strcmp(args[1], "ldap-check")) {
4945 /* use LDAP request to check servers' health */
4946 free(curproxy->check_req);
4947 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004948 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004949 curproxy->options2 |= PR_O2_LDAP_CHK;
4950
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004951 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004952 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4953 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004954 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4955 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004956 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004957 else if (!strcmp(args[1], "spop-check")) {
4958 if (curproxy == &defproxy) {
4959 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4960 file, linenum, args[0], args[1]);
4961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
4963 }
4964 if (curproxy->cap & PR_CAP_FE) {
4965 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4966 file, linenum, args[0], args[1]);
4967 err_code |= ERR_ALERT | ERR_FATAL;
4968 goto out;
4969 }
4970
4971 /* use SPOE request to check servers' health */
4972 free(curproxy->check_req);
4973 curproxy->check_req = NULL;
4974 curproxy->options2 &= ~PR_O2_CHK_ANY;
4975 curproxy->options2 |= PR_O2_SPOP_CHK;
4976
Christopher Faulet8ef75252017-02-20 22:56:03 +01004977 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01004978 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
4981 }
4982 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4983 goto out;
4984 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004985 else if (!strcmp(args[1], "tcp-check")) {
4986 /* use raw TCPCHK send/expect to check servers' health */
4987 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4988 err_code |= ERR_WARN;
4989
4990 free(curproxy->check_req);
4991 curproxy->check_req = NULL;
4992 curproxy->options2 &= ~PR_O2_CHK_ANY;
4993 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004994 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4995 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004996 }
Simon Horman98637e52014-06-20 12:30:16 +09004997 else if (!strcmp(args[1], "external-check")) {
4998 /* excute an external command to check servers' health */
4999 free(curproxy->check_req);
5000 curproxy->check_req = NULL;
5001 curproxy->options2 &= ~PR_O2_CHK_ANY;
5002 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005003 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5004 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005005 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005006 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005007 int cur_arg;
5008
5009 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5010 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005011 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005012
Willy Tarreau87cf5142011-08-19 22:57:24 +02005013 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005014
5015 free(curproxy->fwdfor_hdr_name);
5016 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5017 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5018
5019 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5020 cur_arg = 2;
5021 while (*(args[cur_arg])) {
5022 if (!strcmp(args[cur_arg], "except")) {
5023 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005024 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005025 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5026 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005029 }
5030 /* flush useless bits */
5031 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005032 cur_arg += 2;
5033 } else if (!strcmp(args[cur_arg], "header")) {
5034 /* suboption header - needs additional argument for it */
5035 if (*(args[cur_arg+1]) == 0) {
5036 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5037 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005040 }
5041 free(curproxy->fwdfor_hdr_name);
5042 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5043 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5044 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005045 } else if (!strcmp(args[cur_arg], "if-none")) {
5046 curproxy->options &= ~PR_O_FF_ALWAYS;
5047 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005048 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005049 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005050 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005051 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005054 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005055 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005056 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005057 else if (!strcmp(args[1], "originalto")) {
5058 int cur_arg;
5059
5060 /* insert x-original-to field, but not for the IP address listed as an except.
5061 * set default options (ie: bitfield, header name, etc)
5062 */
5063
5064 curproxy->options |= PR_O_ORGTO;
5065
5066 free(curproxy->orgto_hdr_name);
5067 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5068 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5069
Willy Tarreau87cf5142011-08-19 22:57:24 +02005070 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005071 cur_arg = 2;
5072 while (*(args[cur_arg])) {
5073 if (!strcmp(args[cur_arg], "except")) {
5074 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005075 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 +02005076 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5077 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005080 }
5081 /* flush useless bits */
5082 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5083 cur_arg += 2;
5084 } else if (!strcmp(args[cur_arg], "header")) {
5085 /* suboption header - needs additional argument for it */
5086 if (*(args[cur_arg+1]) == 0) {
5087 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5088 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005091 }
5092 free(curproxy->orgto_hdr_name);
5093 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5094 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5095 cur_arg += 2;
5096 } else {
5097 /* unknown suboption - catchall */
5098 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5099 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005102 }
5103 } /* end while loop */
5104 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 else {
5106 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
Willy Tarreau93893792009-07-23 13:19:11 +02005110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005112 else if (!strcmp(args[0], "default_backend")) {
5113 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005115
5116 if (*(args[1]) == 0) {
5117 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005120 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005121 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005122 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005123
5124 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5125 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005128 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005130
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005131 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5132 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 +01005133 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 /* enable reconnections to dispatch */
5136 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005137
5138 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005141 else if (!strcmp(args[0], "http-reuse")) {
5142 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5143 err_code |= ERR_WARN;
5144
5145 if (strcmp(args[1], "never") == 0) {
5146 /* enable a graceful server shutdown on an HTTP 404 response */
5147 curproxy->options &= ~PR_O_REUSE_MASK;
5148 curproxy->options |= PR_O_REUSE_NEVR;
5149 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5150 goto out;
5151 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005152 else if (strcmp(args[1], "safe") == 0) {
5153 /* enable a graceful server shutdown on an HTTP 404 response */
5154 curproxy->options &= ~PR_O_REUSE_MASK;
5155 curproxy->options |= PR_O_REUSE_SAFE;
5156 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5157 goto out;
5158 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005159 else if (strcmp(args[1], "aggressive") == 0) {
5160 curproxy->options &= ~PR_O_REUSE_MASK;
5161 curproxy->options |= PR_O_REUSE_AGGR;
5162 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5163 goto out;
5164 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005165 else if (strcmp(args[1], "always") == 0) {
5166 /* enable a graceful server shutdown on an HTTP 404 response */
5167 curproxy->options &= ~PR_O_REUSE_MASK;
5168 curproxy->options |= PR_O_REUSE_ALWS;
5169 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5170 goto out;
5171 }
5172 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005173 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
5176 }
5177 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005178 else if (!strcmp(args[0], "http-check")) {
5179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005180 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005181
5182 if (strcmp(args[1], "disable-on-404") == 0) {
5183 /* enable a graceful server shutdown on an HTTP 404 response */
5184 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005185 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5186 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005187 }
Willy Tarreauef781042010-01-27 11:53:01 +01005188 else if (strcmp(args[1], "send-state") == 0) {
5189 /* enable emission of the apparent state of a server in HTTP checks */
5190 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005191 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5192 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005193 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005194 else if (strcmp(args[1], "expect") == 0) {
5195 const char *ptr_arg;
5196 int cur_arg;
5197
5198 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5199 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
5203
5204 cur_arg = 2;
5205 /* consider exclamation marks, sole or at the beginning of a word */
5206 while (*(ptr_arg = args[cur_arg])) {
5207 while (*ptr_arg == '!') {
5208 curproxy->options2 ^= PR_O2_EXP_INV;
5209 ptr_arg++;
5210 }
5211 if (*ptr_arg)
5212 break;
5213 cur_arg++;
5214 }
5215 /* now ptr_arg points to the beginning of a word past any possible
5216 * exclamation mark, and cur_arg is the argument which holds this word.
5217 */
5218 if (strcmp(ptr_arg, "status") == 0) {
5219 if (!*(args[cur_arg + 1])) {
5220 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5221 file, linenum, args[0], args[1], ptr_arg);
5222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
5225 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005226 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005227 curproxy->expect_str = strdup(args[cur_arg + 1]);
5228 }
5229 else if (strcmp(ptr_arg, "string") == 0) {
5230 if (!*(args[cur_arg + 1])) {
5231 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5232 file, linenum, args[0], args[1], ptr_arg);
5233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
5235 }
5236 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005237 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005238 curproxy->expect_str = strdup(args[cur_arg + 1]);
5239 }
5240 else if (strcmp(ptr_arg, "rstatus") == 0) {
5241 if (!*(args[cur_arg + 1])) {
5242 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5243 file, linenum, args[0], args[1], ptr_arg);
5244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246 }
5247 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005248 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005249 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005250 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005251 free(curproxy->expect_regex);
5252 curproxy->expect_regex = NULL;
5253 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005254 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005255 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5256 error = NULL;
5257 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5258 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5259 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5260 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
5263 }
5264 }
5265 else if (strcmp(ptr_arg, "rstring") == 0) {
5266 if (!*(args[cur_arg + 1])) {
5267 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5268 file, linenum, args[0], args[1], ptr_arg);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005273 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005274 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005275 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005276 free(curproxy->expect_regex);
5277 curproxy->expect_regex = NULL;
5278 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005279 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005280 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5281 error = NULL;
5282 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5283 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5284 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5285 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
5289 }
5290 else {
5291 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5292 file, linenum, args[0], args[1], ptr_arg);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005297 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005298 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 +02005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005301 }
5302 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005303 else if (!strcmp(args[0], "tcp-check")) {
5304 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5305 err_code |= ERR_WARN;
5306
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005307 if (strcmp(args[1], "comment") == 0) {
5308 int cur_arg;
5309 struct tcpcheck_rule *tcpcheck;
5310
5311 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005312 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005313 tcpcheck->action = TCPCHK_ACT_COMMENT;
5314
5315 if (!*args[cur_arg + 1]) {
5316 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5317 file, linenum, args[cur_arg]);
5318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
5320 }
5321
5322 tcpcheck->comment = strdup(args[cur_arg + 1]);
5323
5324 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005325 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5326 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005327 }
5328 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005329 const char *ptr_arg;
5330 int cur_arg;
5331 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005332
5333 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005334 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5335 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5336 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5337 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5338 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005339
Willy Tarreau5581c272015-05-13 12:24:53 +02005340 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5341 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5342 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5343 file, linenum);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005346 }
5347
5348 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005349 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005350 tcpcheck->action = TCPCHK_ACT_CONNECT;
5351
5352 /* parsing each parameters to fill up the rule */
5353 while (*(ptr_arg = args[cur_arg])) {
5354 /* tcp port */
5355 if (strcmp(args[cur_arg], "port") == 0) {
5356 if ( (atol(args[cur_arg + 1]) > 65535) ||
5357 (atol(args[cur_arg + 1]) < 1) ){
5358 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5359 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5360 err_code |= ERR_ALERT | ERR_FATAL;
5361 goto out;
5362 }
5363 tcpcheck->port = atol(args[cur_arg + 1]);
5364 cur_arg += 2;
5365 }
5366 /* send proxy protocol */
5367 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5368 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5369 cur_arg++;
5370 }
5371#ifdef USE_OPENSSL
5372 else if (strcmp(args[cur_arg], "ssl") == 0) {
5373 curproxy->options |= PR_O_TCPCHK_SSL;
5374 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5375 cur_arg++;
5376 }
5377#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005378 /* comment for this tcpcheck line */
5379 else if (strcmp(args[cur_arg], "comment") == 0) {
5380 if (!*args[cur_arg + 1]) {
5381 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5382 file, linenum, args[cur_arg]);
5383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
5385 }
5386 tcpcheck->comment = strdup(args[cur_arg + 1]);
5387 cur_arg += 2;
5388 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005389 else {
5390#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005391 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 +01005392#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005393 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 +01005394#endif /* USE_OPENSSL */
5395 file, linenum, args[0], args[1], args[cur_arg]);
5396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
5399
5400 }
5401
5402 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5403 }
5404 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005405 if (! *(args[2]) ) {
5406 /* SEND string expected */
5407 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5408 file, linenum, args[0], args[1], args[2]);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 } else {
5412 struct tcpcheck_rule *tcpcheck;
5413
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005414 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005415
5416 tcpcheck->action = TCPCHK_ACT_SEND;
5417 tcpcheck->string_len = strlen(args[2]);
5418 tcpcheck->string = strdup(args[2]);
5419 tcpcheck->expect_regex = NULL;
5420
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005421 /* comment for this tcpcheck line */
5422 if (strcmp(args[3], "comment") == 0) {
5423 if (!*args[4]) {
5424 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5425 file, linenum, args[3]);
5426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
5429 tcpcheck->comment = strdup(args[4]);
5430 }
5431
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005432 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5433 }
5434 }
5435 else if (strcmp(args[1], "send-binary") == 0) {
5436 if (! *(args[2]) ) {
5437 /* SEND binary string expected */
5438 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5439 file, linenum, args[0], args[1], args[2]);
5440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
5442 } else {
5443 struct tcpcheck_rule *tcpcheck;
5444 char *err = NULL;
5445
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005446 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005447
5448 tcpcheck->action = TCPCHK_ACT_SEND;
5449 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5450 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5451 file, linenum, args[0], args[1], args[2], err);
5452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
5454 }
5455 tcpcheck->expect_regex = NULL;
5456
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005457 /* comment for this tcpcheck line */
5458 if (strcmp(args[3], "comment") == 0) {
5459 if (!*args[4]) {
5460 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5461 file, linenum, args[3]);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
5465 tcpcheck->comment = strdup(args[4]);
5466 }
5467
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005468 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5469 }
5470 }
5471 else if (strcmp(args[1], "expect") == 0) {
5472 const char *ptr_arg;
5473 int cur_arg;
5474 int inverse = 0;
5475
5476 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5477 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
5481
5482 cur_arg = 2;
5483 /* consider exclamation marks, sole or at the beginning of a word */
5484 while (*(ptr_arg = args[cur_arg])) {
5485 while (*ptr_arg == '!') {
5486 inverse = !inverse;
5487 ptr_arg++;
5488 }
5489 if (*ptr_arg)
5490 break;
5491 cur_arg++;
5492 }
5493 /* now ptr_arg points to the beginning of a word past any possible
5494 * exclamation mark, and cur_arg is the argument which holds this word.
5495 */
5496 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005497 struct tcpcheck_rule *tcpcheck;
5498 char *err = NULL;
5499
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005500 if (!*(args[cur_arg + 1])) {
5501 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5502 file, linenum, args[0], args[1], ptr_arg);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005506
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005507 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005508
5509 tcpcheck->action = TCPCHK_ACT_EXPECT;
5510 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5511 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5512 file, linenum, args[0], args[1], args[2], err);
5513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
5515 }
5516 tcpcheck->expect_regex = NULL;
5517 tcpcheck->inverse = inverse;
5518
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005519 /* tcpcheck comment */
5520 cur_arg += 2;
5521 if (strcmp(args[cur_arg], "comment") == 0) {
5522 if (!*args[cur_arg + 1]) {
5523 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5524 file, linenum, args[cur_arg + 1]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528 tcpcheck->comment = strdup(args[cur_arg + 1]);
5529 }
5530
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005531 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5532 }
5533 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005534 struct tcpcheck_rule *tcpcheck;
5535
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005536 if (!*(args[cur_arg + 1])) {
5537 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5538 file, linenum, args[0], args[1], ptr_arg);
5539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005542
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005543 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005544
5545 tcpcheck->action = TCPCHK_ACT_EXPECT;
5546 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5547 tcpcheck->string = strdup(args[cur_arg + 1]);
5548 tcpcheck->expect_regex = NULL;
5549 tcpcheck->inverse = inverse;
5550
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005551 /* tcpcheck comment */
5552 cur_arg += 2;
5553 if (strcmp(args[cur_arg], "comment") == 0) {
5554 if (!*args[cur_arg + 1]) {
5555 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5556 file, linenum, args[cur_arg + 1]);
5557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
5559 }
5560 tcpcheck->comment = strdup(args[cur_arg + 1]);
5561 }
5562
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005563 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5564 }
5565 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005566 struct tcpcheck_rule *tcpcheck;
5567
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005568 if (!*(args[cur_arg + 1])) {
5569 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5570 file, linenum, args[0], args[1], ptr_arg);
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
5573 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005574
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005575 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005576
5577 tcpcheck->action = TCPCHK_ACT_EXPECT;
5578 tcpcheck->string_len = 0;
5579 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005580 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5581 error = NULL;
5582 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5583 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5584 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5585 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
5588 }
5589 tcpcheck->inverse = inverse;
5590
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005591 /* tcpcheck comment */
5592 cur_arg += 2;
5593 if (strcmp(args[cur_arg], "comment") == 0) {
5594 if (!*args[cur_arg + 1]) {
5595 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5596 file, linenum, args[cur_arg + 1]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600 tcpcheck->comment = strdup(args[cur_arg + 1]);
5601 }
5602
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005603 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5604 }
5605 else {
5606 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5607 file, linenum, args[0], args[1], ptr_arg);
5608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
5610 }
5611 }
5612 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005613 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
5616 }
5617 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005618 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005619 if (curproxy == &defproxy) {
5620 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005621 err_code |= ERR_ALERT | ERR_FATAL;
5622 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005623 }
5624
Willy Tarreaub80c2302007-11-30 20:51:32 +01005625 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005627
5628 if (strcmp(args[1], "fail") == 0) {
5629 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005630 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005631 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5632 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005635 }
5636
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005637 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5638 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5639 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005642 }
5643 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5644 }
5645 else {
5646 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005649 }
5650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651#ifdef TPROXY
5652 else if (!strcmp(args[0], "transparent")) {
5653 /* enable transparent proxy connections */
5654 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005655 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 }
5658#endif
5659 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005660 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005661 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005662
Willy Tarreaubaaee002006-06-26 02:48:02 +02005663 if (*(args[1]) == 0) {
5664 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 }
5668 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005669 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005672 else if (!strcmp(args[0], "backlog")) { /* backlog */
5673 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005674 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005675
5676 if (*(args[1]) == 0) {
5677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005680 }
5681 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005682 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5683 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005684 }
Willy Tarreau86034312006-12-29 00:10:33 +01005685 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005686 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005688
Willy Tarreau86034312006-12-29 00:10:33 +01005689 if (*(args[1]) == 0) {
5690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005693 }
5694 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005695 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5696 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5699 if (*(args[1]) == 0) {
5700 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005701 err_code |= ERR_ALERT | ERR_FATAL;
5702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005704 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5705 if (err) {
5706 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5707 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005710 }
5711 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005712 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 }
5715 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005716 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005717 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005718 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005719
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 if (curproxy == &defproxy) {
5721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005725 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005726 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005727
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005728 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005729 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005730 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005731 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005732 goto out;
5733 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005734
5735 proto = protocol_by_family(sk->ss_family);
5736 if (!proto || !proto->connect) {
5737 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5738 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005739 err_code |= ERR_ALERT | ERR_FATAL;
5740 goto out;
5741 }
5742
5743 if (port1 != port2) {
5744 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5745 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005749
5750 if (!port1) {
5751 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5752 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
5755 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005756
William Lallemanddf1425a2015-04-28 20:17:49 +02005757 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5758 goto out;
5759
Willy Tarreaud5191e72010-02-09 20:50:45 +01005760 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005761 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 }
5763 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005764 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005765 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005766
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005767 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5768 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005773 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005774 /**
5775 * The syntax for hash-type config element is
5776 * hash-type {map-based|consistent} [[<algo>] avalanche]
5777 *
5778 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5779 */
5780 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005781
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005782 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5783 err_code |= ERR_WARN;
5784
5785 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005786 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5787 }
5788 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005789 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5790 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005791 else if (strcmp(args[1], "avalanche") == 0) {
5792 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]);
5793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005795 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005796 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005797 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
5800 }
Bhaskar98634f02013-10-29 23:30:51 -04005801
5802 /* set the hash function to use */
5803 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005804 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005805 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005806
5807 /* if consistent with no argument, then avalanche modifier is also applied */
5808 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5809 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005810 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005811 /* set the hash function */
5812 if (!strcmp(args[2], "sdbm")) {
5813 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5814 }
5815 else if (!strcmp(args[2], "djb2")) {
5816 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005817 }
5818 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005819 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005820 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005821 else if (!strcmp(args[2], "crc32")) {
5822 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5823 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005824 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005825 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 -05005826 err_code |= ERR_ALERT | ERR_FATAL;
5827 goto out;
5828 }
5829
5830 /* set the hash modifier */
5831 if (!strcmp(args[3], "avalanche")) {
5832 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5833 }
5834 else if (*args[3]) {
5835 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
5838 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005839 }
William Lallemanda73203e2012-03-12 12:48:57 +01005840 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005841 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5842 if (*(args[1]) == 0) {
5843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
5846 }
5847 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5848 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5849 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
5852 }
5853 }
William Lallemanda73203e2012-03-12 12:48:57 +01005854 else if (strcmp(args[0], "unique-id-format") == 0) {
5855 if (!*(args[1])) {
5856 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
5859 }
William Lallemand3203ff42012-11-11 17:30:56 +01005860 if (*(args[2])) {
5861 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005865 free(curproxy->conf.uniqueid_format_string);
5866 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005867
Willy Tarreau62a61232013-04-12 18:13:46 +02005868 free(curproxy->conf.uif_file);
5869 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5870 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005871 }
William Lallemanda73203e2012-03-12 12:48:57 +01005872
5873 else if (strcmp(args[0], "unique-id-header") == 0) {
5874 if (!*(args[1])) {
5875 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
5878 }
5879 free(curproxy->header_unique_id);
5880 curproxy->header_unique_id = strdup(args[1]);
5881 }
5882
William Lallemand723b73a2012-02-08 16:37:49 +01005883 else if (strcmp(args[0], "log-format") == 0) {
5884 if (!*(args[1])) {
5885 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5886 err_code |= ERR_ALERT | ERR_FATAL;
5887 goto out;
5888 }
William Lallemand3203ff42012-11-11 17:30:56 +01005889 if (*(args[2])) {
5890 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
5893 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005894 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5895 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005896
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005897 if (curproxy->conf.logformat_string == default_http_log_format)
5898 oldlogformat = "option httplog";
5899 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5900 oldlogformat = "option tcplog";
5901 else if (curproxy->conf.logformat_string == clf_http_log_format)
5902 oldlogformat = "option httplog clf";
5903 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5904 file, linenum, oldlogformat);
5905 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005906 if (curproxy->conf.logformat_string != default_http_log_format &&
5907 curproxy->conf.logformat_string != default_tcp_log_format &&
5908 curproxy->conf.logformat_string != clf_http_log_format)
5909 free(curproxy->conf.logformat_string);
5910 curproxy->conf.logformat_string = strdup(args[1]);
5911
5912 free(curproxy->conf.lfs_file);
5913 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5914 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005915
5916 /* get a chance to improve log-format error reporting by
5917 * reporting the correct line-number when possible.
5918 */
5919 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5920 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5921 file, linenum, curproxy->id);
5922 err_code |= ERR_WARN;
5923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005925 else if (!strcmp(args[0], "log-format-sd")) {
5926 if (!*(args[1])) {
5927 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
5930 }
5931 if (*(args[2])) {
5932 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
5936
5937 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5938 free(curproxy->conf.logformat_sd_string);
5939 curproxy->conf.logformat_sd_string = strdup(args[1]);
5940
5941 free(curproxy->conf.lfsd_file);
5942 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5943 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5944
5945 /* get a chance to improve log-format-sd error reporting by
5946 * reporting the correct line-number when possible.
5947 */
5948 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5949 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5950 file, linenum, curproxy->id);
5951 err_code |= ERR_WARN;
5952 }
5953 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005954 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5955 if (*(args[1]) == 0) {
5956 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
5959 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005960 chunk_destroy(&curproxy->log_tag);
5961 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005962 }
William Lallemand0f99e342011-10-12 17:50:54 +02005963 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5964 /* delete previous herited or defined syslog servers */
5965 struct logsrv *back;
5966
5967 if (*(args[1]) != 0) {
5968 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
5972
William Lallemand723b73a2012-02-08 16:37:49 +01005973 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5974 LIST_DEL(&tmplogsrv->list);
5975 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005976 }
5977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005979 struct logsrv *logsrv;
5980
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005982 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005983 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005984 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005985 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005986 LIST_INIT(&node->list);
5987 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 }
5990 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005991 struct sockaddr_storage *sk;
5992 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005993 int arg = 0;
5994 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005995
Vincent Bernat02779b62016-04-03 13:48:43 +02005996 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997
Willy Tarreau18324f52014-06-27 18:10:07 +02005998 /* just after the address, a length may be specified */
5999 if (strcmp(args[arg+2], "len") == 0) {
6000 len = atoi(args[arg+3]);
6001 if (len < 80 || len > 65535) {
6002 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6003 file, linenum, args[arg+3]);
6004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
6006 }
6007 logsrv->maxlen = len;
6008
6009 /* skip these two args */
6010 arg += 2;
6011 }
6012 else
6013 logsrv->maxlen = MAX_SYSLOG_LEN;
6014
6015 if (logsrv->maxlen > global.max_syslog_len) {
6016 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006017 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6018 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6019 logline = my_realloc2(logline, global.max_syslog_len + 1);
6020 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006021 }
6022
Dragan Dosen1322d092015-09-22 16:05:32 +02006023 /* after the length, a format may be specified */
6024 if (strcmp(args[arg+2], "format") == 0) {
6025 logsrv->format = get_log_format(args[arg+3]);
6026 if (logsrv->format < 0) {
6027 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6028 err_code |= ERR_ALERT | ERR_FATAL;
6029 goto out;
6030 }
6031
6032 /* skip these two args */
6033 arg += 2;
6034 }
6035
William Lallemanddf1425a2015-04-28 20:17:49 +02006036 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6037 goto out;
6038
Willy Tarreau18324f52014-06-27 18:10:07 +02006039 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006040 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006041 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045 }
6046
William Lallemand0f99e342011-10-12 17:50:54 +02006047 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006048 if (*(args[arg+3])) {
6049 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006050 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006051 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
6054
Willy Tarreaubaaee002006-06-26 02:48:02 +02006055 }
6056 }
6057
William Lallemand0f99e342011-10-12 17:50:54 +02006058 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006059 if (*(args[arg+4])) {
6060 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006061 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006062 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006063 err_code |= ERR_ALERT | ERR_FATAL;
6064 goto out;
6065
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006066 }
6067 }
6068
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006069 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006070 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006071 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006073 goto out;
6074 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006075
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006076 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006077
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006078 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006079 if (port1 != port2) {
6080 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6081 file, linenum, args[0], args[1]);
6082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
6084 }
6085
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006086 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006087 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006088 }
William Lallemand0f99e342011-10-12 17:50:54 +02006089
6090 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
6092 else {
6093 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6094 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006097 }
6098 }
6099 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006100 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006101 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006102 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006103 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006104
Willy Tarreau977b8e42006-12-29 14:19:17 +01006105 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006107
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006109 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6110 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006111 err_code |= ERR_ALERT | ERR_FATAL;
6112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006114
6115 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006116 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6117 free(curproxy->conn_src.iface_name);
6118 curproxy->conn_src.iface_name = NULL;
6119 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006120
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006121 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006122 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006123 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006124 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006125 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006126 goto out;
6127 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006128
6129 proto = protocol_by_family(sk->ss_family);
6130 if (!proto || !proto->connect) {
6131 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006132 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006133 err_code |= ERR_ALERT | ERR_FATAL;
6134 goto out;
6135 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006136
6137 if (port1 != port2) {
6138 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6139 file, linenum, args[0], args[1]);
6140 err_code |= ERR_ALERT | ERR_FATAL;
6141 goto out;
6142 }
6143
Willy Tarreauef9a3602012-12-08 22:29:20 +01006144 curproxy->conn_src.source_addr = *sk;
6145 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006146
6147 cur_arg = 2;
6148 while (*(args[cur_arg])) {
6149 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006150#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006151 if (!*args[cur_arg + 1]) {
6152 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6153 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006156 }
6157
6158 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006159 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6160 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006161 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006162 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6163 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006164 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6165 char *name, *end;
6166
6167 name = args[cur_arg+1] + 7;
6168 while (isspace(*name))
6169 name++;
6170
6171 end = name;
6172 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6173 end++;
6174
Willy Tarreauef9a3602012-12-08 22:29:20 +01006175 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6176 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6177 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6178 curproxy->conn_src.bind_hdr_len = end - name;
6179 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6180 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6181 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006182
6183 /* now look for an occurrence number */
6184 while (isspace(*end))
6185 end++;
6186 if (*end == ',') {
6187 end++;
6188 name = end;
6189 if (*end == '-')
6190 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006191 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006192 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006193 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006194 }
6195
Willy Tarreauef9a3602012-12-08 22:29:20 +01006196 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006197 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6198 " occurrences values smaller than %d.\n",
6199 file, linenum, MAX_HDR_HISTORY);
6200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
6202 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006203 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006204 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006205
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006206 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006207 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006208 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006209 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006210 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006211 goto out;
6212 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006213
6214 proto = protocol_by_family(sk->ss_family);
6215 if (!proto || !proto->connect) {
6216 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6217 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006218 err_code |= ERR_ALERT | ERR_FATAL;
6219 goto out;
6220 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006221
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006222 if (port1 != port2) {
6223 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6224 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006225 err_code |= ERR_ALERT | ERR_FATAL;
6226 goto out;
6227 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006228 curproxy->conn_src.tproxy_addr = *sk;
6229 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006230 }
6231 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006232#else /* no TPROXY support */
6233 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006234 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006237#endif
6238 cur_arg += 2;
6239 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006240 }
6241
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006242 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6243#ifdef SO_BINDTODEVICE
6244 if (!*args[cur_arg + 1]) {
6245 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006247 err_code |= ERR_ALERT | ERR_FATAL;
6248 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006249 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006250 free(curproxy->conn_src.iface_name);
6251 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6252 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006253 global.last_checks |= LSTCHK_NETADM;
6254#else
6255 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6256 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006257 err_code |= ERR_ALERT | ERR_FATAL;
6258 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006259#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006260 cur_arg += 2;
6261 continue;
6262 }
6263 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006264 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006268 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006269 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6270 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6271 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006272 err_code |= ERR_ALERT | ERR_FATAL;
6273 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006275 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006276 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006281 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006282
6283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006284 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006285 args[0], args[1], args[2], (const char **)args+3);
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], "reqdel")) { /* delete request header from a regex */
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_REMOVE, 0,
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 }
6296 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006298 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 }
6303 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006305 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 }
6310 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006312 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006313 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006317 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006319 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006320 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006321 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006322 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6327 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006328 err_code |= ERR_ALERT | ERR_FATAL;
6329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006331
6332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006333 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006334 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
6338 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006340 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
6345 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006347 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006348 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006366 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006374 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006375
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 if (curproxy == &defproxy) {
6377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006378 err_code |= ERR_ALERT | ERR_FATAL;
6379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006381 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006382 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 if (*(args[1]) == 0) {
6385 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006386 err_code |= ERR_ALERT | ERR_FATAL;
6387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006389
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006390 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006391 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6392 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6393 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006394 err_code |= ERR_ALERT | ERR_FATAL;
6395 goto out;
6396 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006397 err_code |= warnif_cond_conflicts(cond,
6398 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6399 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006400 }
6401 else if (*args[2]) {
6402 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6403 file, linenum, args[0], args[2]);
6404 err_code |= ERR_ALERT | ERR_FATAL;
6405 goto out;
6406 }
6407
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006408 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006409 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006410 wl->s = strdup(args[1]);
6411 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006412 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
6414 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006415 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006418 err_code |= ERR_ALERT | ERR_FATAL;
6419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006421
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006423 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006424 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006430 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
6435 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006437 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006438 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
6442 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006443 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
6449
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006451 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006452 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006453 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
6456 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006458 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006459 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006460 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006465 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006466 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006471 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006472
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 if (curproxy == &defproxy) {
6474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006475 err_code |= ERR_ALERT | ERR_FATAL;
6476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006478 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006479 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 if (*(args[1]) == 0) {
6482 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006483 err_code |= ERR_ALERT | ERR_FATAL;
6484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485 }
6486
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006487 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006488 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6489 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6490 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006491 err_code |= ERR_ALERT | ERR_FATAL;
6492 goto out;
6493 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006494 err_code |= warnif_cond_conflicts(cond,
6495 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6496 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006497 }
6498 else if (*args[2]) {
6499 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6500 file, linenum, args[0], args[2]);
6501 err_code |= ERR_ALERT | ERR_FATAL;
6502 goto out;
6503 }
6504
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006505 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006506 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006507 wl->s = strdup(args[1]);
6508 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 else if (!strcmp(args[0], "errorloc") ||
6511 !strcmp(args[0], "errorloc302") ||
6512 !strcmp(args[0], "errorloc303")) { /* error location */
6513 int errnum, errlen;
6514 char *err;
6515
Willy Tarreau977b8e42006-12-29 14:19:17 +01006516 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006517 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006518
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006520 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006521 err_code |= ERR_ALERT | ERR_FATAL;
6522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
6524
6525 errnum = atol(args[1]);
6526 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006527 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6528 err = malloc(errlen);
6529 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006531 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6532 err = malloc(errlen);
6533 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534 }
6535
Willy Tarreau0f772532006-12-23 20:51:41 +01006536 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6537 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006538 chunk_destroy(&curproxy->errmsg[rc]);
6539 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006540 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006543
6544 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006545 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6546 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 free(err);
6548 }
6549 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006550 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6551 int errnum, errlen, fd;
6552 char *err;
6553 struct stat stat;
6554
6555 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006556 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006557
6558 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006559 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006560 err_code |= ERR_ALERT | ERR_FATAL;
6561 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006562 }
6563
6564 fd = open(args[2], O_RDONLY);
6565 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6566 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6567 file, linenum, args[2], args[1]);
6568 if (fd >= 0)
6569 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006570 err_code |= ERR_ALERT | ERR_FATAL;
6571 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006572 }
6573
Willy Tarreau27a674e2009-08-17 07:23:33 +02006574 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006575 errlen = stat.st_size;
6576 } else {
6577 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006578 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006579 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006580 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006581 }
6582
6583 err = malloc(errlen); /* malloc() must succeed during parsing */
6584 errnum = read(fd, err, errlen);
6585 if (errnum != errlen) {
6586 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6587 file, linenum, args[2], args[1]);
6588 close(fd);
6589 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006590 err_code |= ERR_ALERT | ERR_FATAL;
6591 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006592 }
6593 close(fd);
6594
6595 errnum = atol(args[1]);
6596 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6597 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006598 chunk_destroy(&curproxy->errmsg[rc]);
6599 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006600 break;
6601 }
6602 }
6603
6604 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006605 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6606 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006607 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006608 free(err);
6609 }
6610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006612 struct cfg_kw_list *kwl;
6613 int index;
6614
6615 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6616 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6617 if (kwl->kw[index].section != CFG_LISTEN)
6618 continue;
6619 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6620 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006621 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006622 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006623 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006624 err_code |= ERR_ALERT | ERR_FATAL;
6625 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006626 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006627 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006628 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006629 err_code |= ERR_WARN;
6630 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006631 }
Willy Tarreau93893792009-07-23 13:19:11 +02006632 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006633 }
6634 }
6635 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006636
Willy Tarreau6daf3432008-01-22 16:44:08 +01006637 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006638 err_code |= ERR_ALERT | ERR_FATAL;
6639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006640 }
Willy Tarreau93893792009-07-23 13:19:11 +02006641 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006642 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006643 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006644}
6645
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006646int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006647cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6648{
6649#ifdef CONFIG_HAP_NS
6650 const char *err;
6651 const char *item = args[0];
6652
6653 if (!strcmp(item, "namespace_list")) {
6654 return 0;
6655 }
6656 else if (!strcmp(item, "namespace")) {
6657 size_t idx = 1;
6658 const char *current;
6659 while (*(current = args[idx++])) {
6660 err = invalid_char(current);
6661 if (err) {
6662 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6663 file, linenum, *err, item, current);
6664 return ERR_ALERT | ERR_FATAL;
6665 }
6666
6667 if (netns_store_lookup(current, strlen(current))) {
6668 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6669 file, linenum, current);
6670 return ERR_ALERT | ERR_FATAL;
6671 }
6672 if (!netns_store_insert(current)) {
6673 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6674 file, linenum, current);
6675 return ERR_ALERT | ERR_FATAL;
6676 }
6677 }
6678 }
6679
6680 return 0;
6681#else
6682 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6683 file, linenum);
6684 return ERR_ALERT | ERR_FATAL;
6685#endif
6686}
6687
6688int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6690{
6691
6692 int err_code = 0;
6693 const char *err;
6694
6695 if (!strcmp(args[0], "userlist")) { /* new userlist */
6696 struct userlist *newul;
6697
6698 if (!*args[1]) {
6699 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6700 file, linenum, args[0]);
6701 err_code |= ERR_ALERT | ERR_FATAL;
6702 goto out;
6703 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6705 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006706
6707 err = invalid_char(args[1]);
6708 if (err) {
6709 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6710 file, linenum, *err, args[0], args[1]);
6711 err_code |= ERR_ALERT | ERR_FATAL;
6712 goto out;
6713 }
6714
6715 for (newul = userlist; newul; newul = newul->next)
6716 if (!strcmp(newul->name, args[1])) {
6717 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6718 file, linenum, args[1]);
6719 err_code |= ERR_WARN;
6720 goto out;
6721 }
6722
Vincent Bernat02779b62016-04-03 13:48:43 +02006723 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006724 if (!newul) {
6725 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6726 err_code |= ERR_ALERT | ERR_ABORT;
6727 goto out;
6728 }
6729
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006730 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006731 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6733 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006734 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006735 goto out;
6736 }
6737
6738 newul->next = userlist;
6739 userlist = newul;
6740
6741 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006742 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006743 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006744 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006745
6746 if (!*args[1]) {
6747 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6748 file, linenum, args[0]);
6749 err_code |= ERR_ALERT | ERR_FATAL;
6750 goto out;
6751 }
6752
6753 err = invalid_char(args[1]);
6754 if (err) {
6755 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6756 file, linenum, *err, args[0], args[1]);
6757 err_code |= ERR_ALERT | ERR_FATAL;
6758 goto out;
6759 }
6760
William Lallemand4ac9f542015-05-28 18:03:51 +02006761 if (!userlist)
6762 goto out;
6763
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006764 for (ag = userlist->groups; ag; ag = ag->next)
6765 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6767 file, linenum, args[1], userlist->name);
6768 err_code |= ERR_ALERT;
6769 goto out;
6770 }
6771
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006772 ag = calloc(1, sizeof(*ag));
6773 if (!ag) {
6774 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6775 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006776 goto out;
6777 }
6778
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006779 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006780 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006781 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6782 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006783 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006784 goto out;
6785 }
6786
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006787 cur_arg = 2;
6788
6789 while (*args[cur_arg]) {
6790 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006791 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 cur_arg += 2;
6793 continue;
6794 } else {
6795 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6796 file, linenum, args[0]);
6797 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006798 free(ag->groupusers);
6799 free(ag->name);
6800 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006801 goto out;
6802 }
6803 }
6804
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006805 ag->next = userlist->groups;
6806 userlist->groups = ag;
6807
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006808 } else if (!strcmp(args[0], "user")) { /* new user */
6809 struct auth_users *newuser;
6810 int cur_arg;
6811
6812 if (!*args[1]) {
6813 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6814 file, linenum, args[0]);
6815 err_code |= ERR_ALERT | ERR_FATAL;
6816 goto out;
6817 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006818 if (!userlist)
6819 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006820
6821 for (newuser = userlist->users; newuser; newuser = newuser->next)
6822 if (!strcmp(newuser->user, args[1])) {
6823 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6824 file, linenum, args[1], userlist->name);
6825 err_code |= ERR_ALERT;
6826 goto out;
6827 }
6828
Vincent Bernat02779b62016-04-03 13:48:43 +02006829 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006830 if (!newuser) {
6831 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6832 err_code |= ERR_ALERT | ERR_ABORT;
6833 goto out;
6834 }
6835
6836 newuser->user = strdup(args[1]);
6837
6838 newuser->next = userlist->users;
6839 userlist->users = newuser;
6840
6841 cur_arg = 2;
6842
6843 while (*args[cur_arg]) {
6844 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006845#ifdef CONFIG_HAP_CRYPT
6846 if (!crypt("", args[cur_arg + 1])) {
6847 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6848 file, linenum, newuser->user);
6849 err_code |= ERR_ALERT | ERR_FATAL;
6850 goto out;
6851 }
6852#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006853 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6854 file, linenum);
6855 err_code |= ERR_ALERT;
6856#endif
6857 newuser->pass = strdup(args[cur_arg + 1]);
6858 cur_arg += 2;
6859 continue;
6860 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6861 newuser->pass = strdup(args[cur_arg + 1]);
6862 newuser->flags |= AU_O_INSECURE;
6863 cur_arg += 2;
6864 continue;
6865 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006866 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006867 cur_arg += 2;
6868 continue;
6869 } else {
6870 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6871 file, linenum, args[0]);
6872 err_code |= ERR_ALERT | ERR_FATAL;
6873 goto out;
6874 }
6875 }
6876 } else {
6877 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6878 err_code |= ERR_ALERT | ERR_FATAL;
6879 }
6880
6881out:
6882 return err_code;
6883}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006884
Christopher Faulet79bdef32016-11-04 22:36:15 +01006885int
6886cfg_parse_scope(const char *file, int linenum, char *line)
6887{
6888 char *beg, *end, *scope = NULL;
6889 int err_code = 0;
6890 const char *err;
6891
6892 beg = line + 1;
6893 end = strchr(beg, ']');
6894
6895 /* Detect end of scope declaration */
6896 if (!end || end == beg) {
6897 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6898 file, linenum);
6899 err_code |= ERR_ALERT | ERR_FATAL;
6900 goto out;
6901 }
6902
6903 /* Get scope name and check its validity */
6904 scope = my_strndup(beg, end-beg);
6905 err = invalid_char(scope);
6906 if (err) {
6907 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6908 file, linenum, *err);
6909 err_code |= ERR_ALERT | ERR_ABORT;
6910 goto out;
6911 }
6912
6913 /* Be sure to have a scope declaration alone on its line */
6914 line = end+1;
6915 while (isspace((unsigned char)*line))
6916 line++;
6917 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6918 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6919 file, linenum, *line);
6920 err_code |= ERR_ALERT | ERR_ABORT;
6921 goto out;
6922 }
6923
6924 /* We have a valid scope declaration, save it */
6925 free(cfg_scope);
6926 cfg_scope = scope;
6927 scope = NULL;
6928
6929 out:
6930 free(scope);
6931 return err_code;
6932}
6933
Willy Tarreaubaaee002006-06-26 02:48:02 +02006934/*
6935 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006936 * Returns the error code, 0 if OK, or any combination of :
6937 * - ERR_ABORT: must abort ASAP
6938 * - ERR_FATAL: we can continue parsing but not start the service
6939 * - ERR_WARN: a warning has been emitted
6940 * - ERR_ALERT: an alert has been emitted
6941 * Only the two first ones can stop processing, the two others are just
6942 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006943 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006944int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006945{
William Lallemand64e84512015-05-12 14:25:37 +02006946 char *thisline;
6947 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006948 FILE *f;
6949 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006950 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006951 struct cfg_section *cs = NULL;
6952 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006953 int readbytes = 0;
6954
6955 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006956 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006957 return -1;
6958 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006959
David Carlier97880bb2016-04-08 10:35:26 +01006960 if ((f=fopen(file,"r")) == NULL) {
6961 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006962 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006964
William Lallemandb2f07452015-05-12 14:27:13 +02006965next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006966 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006967 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006968 char *end;
6969 char *args[MAX_LINE_ARGS + 1];
6970 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006971 int dquote = 0; /* double quote */
6972 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006973
Willy Tarreaubaaee002006-06-26 02:48:02 +02006974 linenum++;
6975
6976 end = line + strlen(line);
6977
William Lallemand64e84512015-05-12 14:25:37 +02006978 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006979 /* Check if we reached the limit and the last char is not \n.
6980 * Watch out for the last line without the terminating '\n'!
6981 */
William Lallemand64e84512015-05-12 14:25:37 +02006982 char *newline;
6983 int newlinesize = linesize * 2;
6984
6985 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6986 if (newline == NULL) {
6987 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6988 file, linenum);
6989 err_code |= ERR_ALERT | ERR_FATAL;
6990 continue;
6991 }
6992
6993 readbytes = linesize - 1;
6994 linesize = newlinesize;
6995 thisline = newline;
6996 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006997 }
6998
William Lallemand64e84512015-05-12 14:25:37 +02006999 readbytes = 0;
7000
Willy Tarreaubaaee002006-06-26 02:48:02 +02007001 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007002 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007003 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007004
Christopher Faulet79bdef32016-11-04 22:36:15 +01007005
7006 if (*line == '[') {/* This is the begining if a scope */
7007 err_code |= cfg_parse_scope(file, linenum, line);
7008 goto next_line;
7009 }
7010
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011 arg = 0;
7012 args[arg] = line;
7013
7014 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007015 if (*line == '"' && !squote) { /* double quote outside single quotes */
7016 if (dquote)
7017 dquote = 0;
7018 else
7019 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007020 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007021 end--;
7022 }
7023 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7024 if (squote)
7025 squote = 0;
7026 else
7027 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007028 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007029 end--;
7030 }
7031 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7033 * C equivalent value. Other combinations left unchanged (eg: \1).
7034 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007035 int skip = 0;
7036 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7037 *line = line[1];
7038 skip = 1;
7039 }
7040 else if (line[1] == 'r') {
7041 *line = '\r';
7042 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007044 else if (line[1] == 'n') {
7045 *line = '\n';
7046 skip = 1;
7047 }
7048 else if (line[1] == 't') {
7049 *line = '\t';
7050 skip = 1;
7051 }
7052 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007053 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007054 unsigned char hex1, hex2;
7055 hex1 = toupper(line[2]) - '0';
7056 hex2 = toupper(line[3]) - '0';
7057 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7058 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7059 *line = (hex1<<4) + hex2;
7060 skip = 3;
7061 }
7062 else {
7063 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007064 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007065 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007066 } else if (line[1] == '"') {
7067 *line = '"';
7068 skip = 1;
7069 } else if (line[1] == '\'') {
7070 *line = '\'';
7071 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007072 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7073 *line = '$';
7074 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007075 }
7076 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007077 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007078 end -= skip;
7079 }
7080 line++;
7081 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007082 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007083 /* end of string, end of loop */
7084 *line = 0;
7085 break;
7086 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007087 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007089 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007090 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007091 line++;
7092 args[++arg] = line;
7093 }
William Lallemandb2f07452015-05-12 14:27:13 +02007094 else if (dquote && *line == '$') {
7095 /* environment variables are evaluated inside double quotes */
7096 char *var_beg;
7097 char *var_end;
7098 char save_char;
7099 char *value;
7100 int val_len;
7101 int newlinesize;
7102 int braces = 0;
7103
7104 var_beg = line + 1;
7105 var_end = var_beg;
7106
7107 if (*var_beg == '{') {
7108 var_beg++;
7109 var_end++;
7110 braces = 1;
7111 }
7112
7113 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7114 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7115 err_code |= ERR_ALERT | ERR_FATAL;
7116 goto next_line; /* skip current line */
7117 }
7118
7119 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7120 var_end++;
7121
7122 save_char = *var_end;
7123 *var_end = '\0';
7124 value = getenv(var_beg);
7125 *var_end = save_char;
7126 val_len = value ? strlen(value) : 0;
7127
7128 if (braces) {
7129 if (*var_end == '}') {
7130 var_end++;
7131 braces = 0;
7132 } else {
7133 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7134 err_code |= ERR_ALERT | ERR_FATAL;
7135 goto next_line; /* skip current line */
7136 }
7137 }
7138
7139 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7140
7141 /* if not enough space in thisline */
7142 if (newlinesize > linesize) {
7143 char *newline;
7144
7145 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7146 if (newline == NULL) {
7147 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7148 err_code |= ERR_ALERT | ERR_FATAL;
7149 goto next_line; /* slip current line */
7150 }
7151 /* recompute pointers if realloc returns a new pointer */
7152 if (newline != thisline) {
7153 int i;
7154 int diff;
7155
7156 for (i = 0; i <= arg; i++) {
7157 diff = args[i] - thisline;
7158 args[i] = newline + diff;
7159 }
7160
7161 diff = var_end - thisline;
7162 var_end = newline + diff;
7163 diff = end - thisline;
7164 end = newline + diff;
7165 diff = line - thisline;
7166 line = newline + diff;
7167 thisline = newline;
7168 }
7169 linesize = newlinesize;
7170 }
7171
7172 /* insert value inside the line */
7173 memmove(line + val_len, var_end, end - var_end + 1);
7174 memcpy(line, value, val_len);
7175 end += val_len - (var_end - line);
7176 line += val_len;
7177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007178 else {
7179 line++;
7180 }
7181 }
William Lallemandb2f07452015-05-12 14:27:13 +02007182
William Lallemandf9873ba2015-05-05 17:37:14 +02007183 if (dquote) {
7184 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7185 err_code |= ERR_ALERT | ERR_FATAL;
7186 }
7187
7188 if (squote) {
7189 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7190 err_code |= ERR_ALERT | ERR_FATAL;
7191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007192
7193 /* empty line */
7194 if (!**args)
7195 continue;
7196
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007197 if (*line) {
7198 /* we had to stop due to too many args.
7199 * Let's terminate the string, print the offending part then cut the
7200 * last arg.
7201 */
7202 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7203 line++;
7204 *line = '\0';
7205
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007206 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007207 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007208 err_code |= ERR_ALERT | ERR_FATAL;
7209 args[arg] = line;
7210 }
7211
Willy Tarreau540abe42007-05-02 20:50:16 +02007212 /* zero out remaining args and ensure that at least one entry
7213 * is zeroed out.
7214 */
7215 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007216 args[arg] = line;
7217 }
7218
Willy Tarreau3842f002009-06-14 11:39:52 +02007219 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007220 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007221 char *tmp;
7222
Willy Tarreau3842f002009-06-14 11:39:52 +02007223 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007224 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007225 for (arg=0; *args[arg+1]; arg++)
7226 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007227 *tmp = '\0'; // fix the next arg to \0
7228 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007229 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007230 else if (!strcmp(args[0], "default")) {
7231 kwm = KWM_DEF;
7232 for (arg=0; *args[arg+1]; arg++)
7233 args[arg] = args[arg+1]; // shift args after inversion
7234 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007235
William Lallemand0f99e342011-10-12 17:50:54 +02007236 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7237 strcmp(args[0], "log") != 0) {
7238 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007239 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007240 }
7241
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007242 /* detect section start */
7243 list_for_each_entry(ics, &sections, list) {
7244 if (strcmp(args[0], ics->section_name) == 0) {
7245 cursection = ics->section_name;
7246 cs = ics;
7247 break;
7248 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007249 }
7250
Willy Tarreaubaaee002006-06-26 02:48:02 +02007251 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007252 if (cs)
7253 err_code |= cs->section_parser(file, linenum, args, kwm);
7254 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007255 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007256 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007258
7259 if (err_code & ERR_ABORT)
7260 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007261 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007262 free(cfg_scope);
7263 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007264 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007265 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007266 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007267 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007268}
7269
Willy Tarreau64ab6072014-09-16 12:17:36 +02007270/* This function propagates processes from frontend <from> to backend <to> so
7271 * that it is always guaranteed that a backend pointed to by a frontend is
7272 * bound to all of its processes. After that, if the target is a "listen"
7273 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007274 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007275 * checked first to ensure that <to> is already bound to all processes of
7276 * <from>, there is no risk of looping and we ensure to follow the shortest
7277 * path to the destination.
7278 *
7279 * It is possible to set <to> to NULL for the first call so that the function
7280 * takes care of visiting the initial frontend in <from>.
7281 *
7282 * It is important to note that the function relies on the fact that all names
7283 * have already been resolved.
7284 */
7285void propagate_processes(struct proxy *from, struct proxy *to)
7286{
7287 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007288
7289 if (to) {
7290 /* check whether we need to go down */
7291 if (from->bind_proc &&
7292 (from->bind_proc & to->bind_proc) == from->bind_proc)
7293 return;
7294
7295 if (!from->bind_proc && !to->bind_proc)
7296 return;
7297
7298 to->bind_proc = from->bind_proc ?
7299 (to->bind_proc | from->bind_proc) : 0;
7300
7301 /* now propagate down */
7302 from = to;
7303 }
7304
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007305 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007306 return;
7307
Willy Tarreauf6b70012014-12-18 14:00:43 +01007308 if (from->state == PR_STSTOPPED)
7309 return;
7310
Willy Tarreau64ab6072014-09-16 12:17:36 +02007311 /* default_backend */
7312 if (from->defbe.be)
7313 propagate_processes(from, from->defbe.be);
7314
7315 /* use_backend */
7316 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007317 if (rule->dynamic)
7318 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007319 to = rule->be.backend;
7320 propagate_processes(from, to);
7321 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007322}
7323
Willy Tarreaubb925012009-07-23 13:36:36 +02007324/*
7325 * Returns the error code, 0 if OK, or any combination of :
7326 * - ERR_ABORT: must abort ASAP
7327 * - ERR_FATAL: we can continue parsing but not start the service
7328 * - ERR_WARN: a warning has been emitted
7329 * - ERR_ALERT: an alert has been emitted
7330 * Only the two first ones can stop processing, the two others are just
7331 * indicators.
7332 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007333int check_config_validity()
7334{
7335 int cfgerr = 0;
7336 struct proxy *curproxy = NULL;
7337 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007338 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007339 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007340 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007341 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007342
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007343 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007344 /*
7345 * Now, check for the integrity of all that we have collected.
7346 */
7347
7348 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007349 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007350
Willy Tarreau193b8c62012-11-22 00:17:38 +01007351 if (!global.tune.max_http_hdr)
7352 global.tune.max_http_hdr = MAX_HTTP_HDR;
7353
7354 if (!global.tune.cookie_len)
7355 global.tune.cookie_len = CAPTURE_LEN;
7356
7357 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7358
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007359 /* Post initialisation of the users and groups lists. */
7360 err_code = userlist_postinit();
7361 if (err_code != ERR_NONE)
7362 goto out;
7363
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007364 /* first, we will invert the proxy list order */
7365 curproxy = NULL;
7366 while (proxy) {
7367 struct proxy *next;
7368
7369 next = proxy->next;
7370 proxy->next = curproxy;
7371 curproxy = proxy;
7372 if (!next)
7373 break;
7374 proxy = next;
7375 }
7376
Willy Tarreau419ead82014-09-16 13:41:21 +02007377 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007378 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007379 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007380 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007381 struct act_rule *trule;
7382 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007383 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007384 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007385 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007386
Willy Tarreau050536d2012-10-04 08:47:34 +02007387 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007388 /* proxy ID not set, use automatic numbering with first
7389 * spare entry starting with next_pxid.
7390 */
7391 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7392 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7393 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007394 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007395 next_pxid++;
7396
Willy Tarreau55ea7572007-06-17 19:56:27 +02007397
Willy Tarreaubaaee002006-06-26 02:48:02 +02007398 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007399 /* ensure we don't keep listeners uselessly bound */
7400 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007401 free((void *)curproxy->table.peers.name);
7402 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007403 continue;
7404 }
7405
Willy Tarreau102df612014-05-07 23:56:38 +02007406 /* Check multi-process mode compatibility for the current proxy */
7407
7408 if (curproxy->bind_proc) {
7409 /* an explicit bind-process was specified, let's check how many
7410 * processes remain.
7411 */
David Carliere6c39412015-07-02 07:00:17 +00007412 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007413
7414 curproxy->bind_proc &= nbits(global.nbproc);
7415 if (!curproxy->bind_proc && nbproc == 1) {
7416 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);
7417 curproxy->bind_proc = 1;
7418 }
7419 else if (!curproxy->bind_proc && nbproc > 1) {
7420 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);
7421 curproxy->bind_proc = 0;
7422 }
7423 }
7424
Willy Tarreau3d209582014-05-09 17:06:11 +02007425 /* check and reduce the bind-proc of each listener */
7426 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7427 unsigned long mask;
7428
7429 if (!bind_conf->bind_proc)
7430 continue;
7431
7432 mask = nbits(global.nbproc);
7433 if (curproxy->bind_proc)
7434 mask &= curproxy->bind_proc;
7435 /* mask cannot be null here thanks to the previous checks */
7436
David Carliere6c39412015-07-02 07:00:17 +00007437 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007438 bind_conf->bind_proc &= mask;
7439
7440 if (!bind_conf->bind_proc && nbproc == 1) {
7441 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",
7442 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7443 bind_conf->bind_proc = mask & ~(mask - 1);
7444 }
7445 else if (!bind_conf->bind_proc && nbproc > 1) {
7446 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",
7447 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7448 bind_conf->bind_proc = 0;
7449 }
7450 }
7451
Willy Tarreauff01a212009-03-15 13:46:16 +01007452 switch (curproxy->mode) {
7453 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007454 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007455 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007456 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7457 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007458 cfgerr++;
7459 }
7460
7461 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007462 Warning("config : servers will be ignored for %s '%s'.\n",
7463 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007464 break;
7465
7466 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007467 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007468 break;
7469
7470 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007471 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007472 break;
7473 }
7474
Willy Tarreauf3934b82015-08-11 11:36:45 +02007475 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7476 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7477 proxy_type_str(curproxy), curproxy->id);
7478 err_code |= ERR_WARN;
7479 }
7480
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007481 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007482 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007483 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007484 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7485 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007486 cfgerr++;
7487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007488#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007489 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007490 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7491 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007492 cfgerr++;
7493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007494#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007495 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007496 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7497 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007498 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007499 }
7500 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007501 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007502 /* If no LB algo is set in a backend, and we're not in
7503 * transparent mode, dispatch mode nor proxy mode, we
7504 * want to use balance roundrobin by default.
7505 */
7506 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7507 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007508 }
7509 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007510
Willy Tarreau1620ec32011-08-06 17:05:02 +02007511 if (curproxy->options & PR_O_DISPATCH)
7512 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7513 else if (curproxy->options & PR_O_HTTP_PROXY)
7514 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7515 else if (curproxy->options & PR_O_TRANSP)
7516 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007517
Willy Tarreau1620ec32011-08-06 17:05:02 +02007518 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7519 if (curproxy->options & PR_O_DISABLE404) {
7520 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7521 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7522 err_code |= ERR_WARN;
7523 curproxy->options &= ~PR_O_DISABLE404;
7524 }
7525 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7526 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7527 "send-state", proxy_type_str(curproxy), curproxy->id);
7528 err_code |= ERR_WARN;
7529 curproxy->options &= ~PR_O2_CHK_SNDST;
7530 }
Willy Tarreauef781042010-01-27 11:53:01 +01007531 }
7532
Simon Horman98637e52014-06-20 12:30:16 +09007533 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7534 if (!global.external_check) {
7535 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7536 curproxy->id, "option external-check");
7537 cfgerr++;
7538 }
7539 if (!curproxy->check_command) {
7540 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7541 curproxy->id, "option external-check");
7542 cfgerr++;
7543 }
7544 }
7545
Simon Horman64e34162015-02-06 11:11:57 +09007546 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007547 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7548 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007549 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7550 "'email-alert myhostname', or 'email-alert to' "
7551 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007552 "to be present).\n",
7553 proxy_type_str(curproxy), curproxy->id);
7554 err_code |= ERR_WARN;
7555 free_email_alert(curproxy);
7556 }
7557 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007558 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007559 }
7560
Simon Horman98637e52014-06-20 12:30:16 +09007561 if (curproxy->check_command) {
7562 int clear = 0;
7563 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7564 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7565 "external-check command", proxy_type_str(curproxy), curproxy->id);
7566 err_code |= ERR_WARN;
7567 clear = 1;
7568 }
7569 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007570 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007571 curproxy->id, "external-check command");
7572 cfgerr++;
7573 }
7574 if (clear) {
7575 free(curproxy->check_command);
7576 curproxy->check_command = NULL;
7577 }
7578 }
7579
7580 if (curproxy->check_path) {
7581 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7582 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7583 "external-check path", proxy_type_str(curproxy), curproxy->id);
7584 err_code |= ERR_WARN;
7585 free(curproxy->check_path);
7586 curproxy->check_path = NULL;
7587 }
7588 }
7589
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007590 /* if a default backend was specified, let's find it */
7591 if (curproxy->defbe.name) {
7592 struct proxy *target;
7593
Willy Tarreauafb39922015-05-26 12:04:09 +02007594 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007595 if (!target) {
7596 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7597 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007598 cfgerr++;
7599 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007600 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7601 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007602 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007603 } else if (target->mode != curproxy->mode &&
7604 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7605
7606 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7607 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7608 curproxy->conf.file, curproxy->conf.line,
7609 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7610 target->conf.file, target->conf.line);
7611 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007612 } else {
7613 free(curproxy->defbe.name);
7614 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007615 /* Update tot_fe_maxconn for a further fullconn's computation */
7616 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007617 /* Emit a warning if this proxy also has some servers */
7618 if (curproxy->srv) {
7619 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7620 curproxy->id);
7621 err_code |= ERR_WARN;
7622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007623 }
7624 }
7625
Emeric Brun3f783572017-01-12 11:21:28 +01007626 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7627 /* Case of listen without default backend
7628 * The curproxy will be its own default backend
7629 * so we update tot_fe_maxconn for a further
7630 * fullconn's computation */
7631 curproxy->tot_fe_maxconn += curproxy->maxconn;
7632 }
7633
Willy Tarreau55ea7572007-06-17 19:56:27 +02007634 /* find the target proxy for 'use_backend' rules */
7635 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007636 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007637 struct logformat_node *node;
7638 char *pxname;
7639
7640 /* Try to parse the string as a log format expression. If the result
7641 * of the parsing is only one entry containing a simple string, then
7642 * it's a standard string corresponding to a static rule, thus the
7643 * parsing is cancelled and be.name is restored to be resolved.
7644 */
7645 pxname = rule->be.name;
7646 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007647 curproxy->conf.args.ctx = ARGC_UBK;
7648 curproxy->conf.args.file = rule->file;
7649 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007650 err = NULL;
7651 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7652 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7653 rule->file, rule->line, pxname, err);
7654 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007655 cfgerr++;
7656 continue;
7657 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007658 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7659
7660 if (!LIST_ISEMPTY(&rule->be.expr)) {
7661 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7662 rule->dynamic = 1;
7663 free(pxname);
7664 continue;
7665 }
7666 /* simple string: free the expression and fall back to static rule */
7667 free(node->arg);
7668 free(node);
7669 }
7670
7671 rule->dynamic = 0;
7672 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007673
Willy Tarreauafb39922015-05-26 12:04:09 +02007674 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007675 if (!target) {
7676 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7677 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007678 cfgerr++;
7679 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007680 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7681 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007682 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007683 } else if (target->mode != curproxy->mode &&
7684 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7685
7686 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7687 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7688 curproxy->conf.file, curproxy->conf.line,
7689 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7690 target->conf.file, target->conf.line);
7691 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007692 } else {
7693 free((void *)rule->be.name);
7694 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007695 /* For each target of switching rules, we update
7696 * their tot_fe_maxconn, except if a previous rule point
7697 * on the same backend or on the default backend */
7698 if (rule->be.backend != curproxy->defbe.be) {
7699 struct switching_rule *swrule;
7700
7701 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7702 if (rule == swrule) {
7703 target->tot_fe_maxconn += curproxy->maxconn;
7704 break;
7705 }
7706 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7707 /* there is multiple ref of this backend */
7708 break;
7709 }
7710 }
7711 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007712 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007713 }
7714
Willy Tarreau64ab6072014-09-16 12:17:36 +02007715 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007716 list_for_each_entry(srule, &curproxy->server_rules, list) {
7717 struct server *target = findserver(curproxy, srule->srv.name);
7718
7719 if (!target) {
7720 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7721 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7722 cfgerr++;
7723 continue;
7724 }
7725 free((void *)srule->srv.name);
7726 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007727 }
7728
Emeric Brunb982a3d2010-01-04 15:45:53 +01007729 /* find the target table for 'stick' rules */
7730 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7731 struct proxy *target;
7732
Emeric Brun1d33b292010-01-04 15:47:17 +01007733 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7734 if (mrule->flags & STK_IS_STORE)
7735 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7736
Emeric Brunb982a3d2010-01-04 15:45:53 +01007737 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007738 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007739 else
7740 target = curproxy;
7741
7742 if (!target) {
7743 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7744 curproxy->id, mrule->table.name);
7745 cfgerr++;
7746 }
7747 else if (target->table.size == 0) {
7748 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7749 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7750 cfgerr++;
7751 }
Willy Tarreau12785782012-04-27 21:37:17 +02007752 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7753 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007754 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7755 cfgerr++;
7756 }
7757 else {
7758 free((void *)mrule->table.name);
7759 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007760 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007761 }
7762 }
7763
7764 /* find the target table for 'store response' rules */
7765 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7766 struct proxy *target;
7767
Emeric Brun1d33b292010-01-04 15:47:17 +01007768 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7769
Emeric Brunb982a3d2010-01-04 15:45:53 +01007770 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007771 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007772 else
7773 target = curproxy;
7774
7775 if (!target) {
7776 Alert("Proxy '%s': unable to find store table '%s'.\n",
7777 curproxy->id, mrule->table.name);
7778 cfgerr++;
7779 }
7780 else if (target->table.size == 0) {
7781 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7782 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7783 cfgerr++;
7784 }
Willy Tarreau12785782012-04-27 21:37:17 +02007785 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7786 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007787 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7788 cfgerr++;
7789 }
7790 else {
7791 free((void *)mrule->table.name);
7792 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007793 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007794 }
7795 }
7796
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007797 /* find the target table for 'tcp-request' layer 4 rules */
7798 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7799 struct proxy *target;
7800
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007801 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007802 continue;
7803
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007804 if (trule->arg.trk_ctr.table.n)
7805 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007806 else
7807 target = curproxy;
7808
7809 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007810 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007811 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007812 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007813 cfgerr++;
7814 }
7815 else if (target->table.size == 0) {
7816 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007817 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007818 cfgerr++;
7819 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007820 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007821 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007822 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007823 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007824 cfgerr++;
7825 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007826 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007827 free(trule->arg.trk_ctr.table.n);
7828 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007829 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007830 * to pass a list of counters to track and allocate them right here using
7831 * stktable_alloc_data_type().
7832 */
7833 }
7834 }
7835
Willy Tarreau620408f2016-10-21 16:37:51 +02007836 /* find the target table for 'tcp-request' layer 5 rules */
7837 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7838 struct proxy *target;
7839
7840 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7841 continue;
7842
7843 if (trule->arg.trk_ctr.table.n)
7844 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7845 else
7846 target = curproxy;
7847
7848 if (!target) {
7849 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7850 curproxy->id, trule->arg.trk_ctr.table.n,
7851 tcp_trk_idx(trule->action));
7852 cfgerr++;
7853 }
7854 else if (target->table.size == 0) {
7855 Alert("Proxy '%s': table '%s' used but not configured.\n",
7856 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7857 cfgerr++;
7858 }
7859 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7860 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7861 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7862 tcp_trk_idx(trule->action));
7863 cfgerr++;
7864 }
7865 else {
7866 free(trule->arg.trk_ctr.table.n);
7867 trule->arg.trk_ctr.table.t = &target->table;
7868 /* Note: if we decide to enhance the track-sc syntax, we may be able
7869 * to pass a list of counters to track and allocate them right here using
7870 * stktable_alloc_data_type().
7871 */
7872 }
7873 }
7874
Willy Tarreaud1f96522010-08-03 19:34:32 +02007875 /* find the target table for 'tcp-request' layer 6 rules */
7876 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7877 struct proxy *target;
7878
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007879 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007880 continue;
7881
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007882 if (trule->arg.trk_ctr.table.n)
7883 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007884 else
7885 target = curproxy;
7886
7887 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007888 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007889 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007890 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007891 cfgerr++;
7892 }
7893 else if (target->table.size == 0) {
7894 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007895 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007896 cfgerr++;
7897 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007898 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007899 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007900 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007901 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007902 cfgerr++;
7903 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007904 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007905 free(trule->arg.trk_ctr.table.n);
7906 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007907 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007908 * to pass a list of counters to track and allocate them right here using
7909 * stktable_alloc_data_type().
7910 */
7911 }
7912 }
7913
Baptiste Assmanne9544932015-11-03 23:31:35 +01007914 /* parse http-request capture rules to ensure id really exists */
7915 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7916 if (hrqrule->action != ACT_CUSTOM ||
7917 hrqrule->action_ptr != http_action_req_capture_by_id)
7918 continue;
7919
7920 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7921 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7922 curproxy->id, hrqrule->arg.capid.idx);
7923 cfgerr++;
7924 }
7925 }
7926
7927 /* parse http-response capture rules to ensure id really exists */
7928 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7929 if (hrqrule->action != ACT_CUSTOM ||
7930 hrqrule->action_ptr != http_action_res_capture_by_id)
7931 continue;
7932
7933 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7934 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7935 curproxy->id, hrqrule->arg.capid.idx);
7936 cfgerr++;
7937 }
7938 }
7939
Willy Tarreau09448f72014-06-25 18:12:15 +02007940 /* find the target table for 'http-request' layer 7 rules */
7941 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7942 struct proxy *target;
7943
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007944 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007945 continue;
7946
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007947 if (hrqrule->arg.trk_ctr.table.n)
7948 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007949 else
7950 target = curproxy;
7951
7952 if (!target) {
7953 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007954 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007955 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007956 cfgerr++;
7957 }
7958 else if (target->table.size == 0) {
7959 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007960 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007961 cfgerr++;
7962 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007963 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007964 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007965 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007966 http_trk_idx(hrqrule->action));
7967 cfgerr++;
7968 }
7969 else {
7970 free(hrqrule->arg.trk_ctr.table.n);
7971 hrqrule->arg.trk_ctr.table.t = &target->table;
7972 /* Note: if we decide to enhance the track-sc syntax, we may be able
7973 * to pass a list of counters to track and allocate them right here using
7974 * stktable_alloc_data_type().
7975 */
7976 }
7977 }
7978
7979 /* find the target table for 'http-response' layer 7 rules */
7980 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7981 struct proxy *target;
7982
7983 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7984 continue;
7985
7986 if (hrqrule->arg.trk_ctr.table.n)
7987 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7988 else
7989 target = curproxy;
7990
7991 if (!target) {
7992 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7993 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7994 http_trk_idx(hrqrule->action));
7995 cfgerr++;
7996 }
7997 else if (target->table.size == 0) {
7998 Alert("Proxy '%s': table '%s' used but not configured.\n",
7999 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8000 cfgerr++;
8001 }
8002 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8003 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8004 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8005 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008006 cfgerr++;
8007 }
8008 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008009 free(hrqrule->arg.trk_ctr.table.n);
8010 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008011 /* Note: if we decide to enhance the track-sc syntax, we may be able
8012 * to pass a list of counters to track and allocate them right here using
8013 * stktable_alloc_data_type().
8014 */
8015 }
8016 }
8017
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008018 /* move any "block" rules at the beginning of the http-request rules */
8019 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8020 /* insert block_rules into http_req_rules at the beginning */
8021 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8022 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8023 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8024 curproxy->http_req_rules.n = curproxy->block_rules.n;
8025 LIST_INIT(&curproxy->block_rules);
8026 }
8027
Emeric Brun32da3c42010-09-23 18:39:19 +02008028 if (curproxy->table.peers.name) {
8029 struct peers *curpeers = peers;
8030
8031 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8032 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8033 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008034 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008035 break;
8036 }
8037 }
8038
8039 if (!curpeers) {
8040 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8041 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008042 free((void *)curproxy->table.peers.name);
8043 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008044 cfgerr++;
8045 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008046 else if (curpeers->state == PR_STSTOPPED) {
8047 /* silently disable this peers section */
8048 curproxy->table.peers.p = NULL;
8049 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008050 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008051 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8052 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008053 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008054 cfgerr++;
8055 }
8056 }
8057
Simon Horman9dc49962015-01-30 11:22:59 +09008058
8059 if (curproxy->email_alert.mailers.name) {
8060 struct mailers *curmailers = mailers;
8061
8062 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8063 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8064 free(curproxy->email_alert.mailers.name);
8065 curproxy->email_alert.mailers.m = curmailers;
8066 curmailers->users++;
8067 break;
8068 }
8069 }
8070
8071 if (!curmailers) {
8072 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8073 curproxy->id, curproxy->email_alert.mailers.name);
8074 free_email_alert(curproxy);
8075 cfgerr++;
8076 }
8077 }
8078
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008079 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008080 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008081 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8082 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8083 "proxy", curproxy->id);
8084 cfgerr++;
8085 goto out_uri_auth_compat;
8086 }
8087
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008088 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008089 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008090 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008091 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008092
Willy Tarreau95fa4692010-02-01 13:05:50 +01008093 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8094 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008095
8096 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008097 uri_auth_compat_req[i++] = "realm";
8098 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8099 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008100
Willy Tarreau95fa4692010-02-01 13:05:50 +01008101 uri_auth_compat_req[i++] = "unless";
8102 uri_auth_compat_req[i++] = "{";
8103 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8104 uri_auth_compat_req[i++] = "}";
8105 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008106
Willy Tarreauff011f22011-01-06 17:51:27 +01008107 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8108 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008109 cfgerr++;
8110 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008111 }
8112
Willy Tarreauff011f22011-01-06 17:51:27 +01008113 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008114
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008115 if (curproxy->uri_auth->auth_realm) {
8116 free(curproxy->uri_auth->auth_realm);
8117 curproxy->uri_auth->auth_realm = NULL;
8118 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008119
8120 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008121 }
8122out_uri_auth_compat:
8123
Dragan Dosen43885c72015-10-01 13:18:13 +02008124 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008125 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008126 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8127 if (!curproxy->conf.logformat_sd_string) {
8128 /* set the default logformat_sd_string */
8129 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8130 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008131 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008132 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008133 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008134
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008135 /* compile the log format */
8136 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008137 if (curproxy->conf.logformat_string != default_http_log_format &&
8138 curproxy->conf.logformat_string != default_tcp_log_format &&
8139 curproxy->conf.logformat_string != clf_http_log_format)
8140 free(curproxy->conf.logformat_string);
8141 curproxy->conf.logformat_string = NULL;
8142 free(curproxy->conf.lfs_file);
8143 curproxy->conf.lfs_file = NULL;
8144 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008145
8146 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8147 free(curproxy->conf.logformat_sd_string);
8148 curproxy->conf.logformat_sd_string = NULL;
8149 free(curproxy->conf.lfsd_file);
8150 curproxy->conf.lfsd_file = NULL;
8151 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008152 }
8153
Willy Tarreau62a61232013-04-12 18:13:46 +02008154 if (curproxy->conf.logformat_string) {
8155 curproxy->conf.args.ctx = ARGC_LOG;
8156 curproxy->conf.args.file = curproxy->conf.lfs_file;
8157 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008158 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008159 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008160 SMP_VAL_FE_LOG_END, &err)) {
8161 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8162 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8163 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008164 cfgerr++;
8165 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008166 curproxy->conf.args.file = NULL;
8167 curproxy->conf.args.line = 0;
8168 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008169
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008170 if (curproxy->conf.logformat_sd_string) {
8171 curproxy->conf.args.ctx = ARGC_LOGSD;
8172 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8173 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008174 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008175 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 +01008176 SMP_VAL_FE_LOG_END, &err)) {
8177 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8178 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8179 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008180 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008181 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8182 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8183 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8184 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008185 cfgerr++;
8186 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008187 curproxy->conf.args.file = NULL;
8188 curproxy->conf.args.line = 0;
8189 }
8190
Willy Tarreau62a61232013-04-12 18:13:46 +02008191 if (curproxy->conf.uniqueid_format_string) {
8192 curproxy->conf.args.ctx = ARGC_UIF;
8193 curproxy->conf.args.file = curproxy->conf.uif_file;
8194 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008195 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008196 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 +01008197 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8198 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8199 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8200 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008201 cfgerr++;
8202 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008203 curproxy->conf.args.file = NULL;
8204 curproxy->conf.args.line = 0;
8205 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008206
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008207 /* only now we can check if some args remain unresolved.
8208 * This must be done after the users and groups resolution.
8209 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008210 cfgerr += smp_resolve_args(curproxy);
8211 if (!cfgerr)
8212 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008213
Willy Tarreau2738a142006-07-08 17:28:09 +02008214 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008215 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008216 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008217 (!curproxy->timeout.connect ||
8218 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008219 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008220 " | While not properly invalid, you will certainly encounter various problems\n"
8221 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008222 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008223 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008224 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008225 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008226
Willy Tarreau1fa31262007-12-03 00:36:16 +01008227 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8228 * We must still support older configurations, so let's find out whether those
8229 * parameters have been set or must be copied from contimeouts.
8230 */
8231 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008232 if (!curproxy->timeout.tarpit ||
8233 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008234 /* tarpit timeout not set. We search in the following order:
8235 * default.tarpit, curr.connect, default.connect.
8236 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008237 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008238 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008239 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008240 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008241 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008242 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008243 }
8244 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008245 (!curproxy->timeout.queue ||
8246 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008247 /* queue timeout not set. We search in the following order:
8248 * default.queue, curr.connect, default.connect.
8249 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008250 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008251 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008252 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008253 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008254 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008255 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008256 }
8257 }
8258
Willy Tarreau1620ec32011-08-06 17:05:02 +02008259 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008260 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008261 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008262 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008263 }
8264
Willy Tarreau215663d2014-06-13 18:30:23 +02008265 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8266 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8267 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8268 proxy_type_str(curproxy), curproxy->id);
8269 err_code |= ERR_WARN;
8270 }
8271
Willy Tarreau193b8c62012-11-22 00:17:38 +01008272 /* ensure that cookie capture length is not too large */
8273 if (curproxy->capture_len >= global.tune.cookie_len) {
8274 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8275 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8276 err_code |= ERR_WARN;
8277 curproxy->capture_len = global.tune.cookie_len - 1;
8278 }
8279
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008280 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008281 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008282 curproxy->req_cap_pool = create_pool("ptrcap",
8283 curproxy->nb_req_cap * sizeof(char *),
8284 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008285 }
8286
8287 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008288 curproxy->rsp_cap_pool = create_pool("ptrcap",
8289 curproxy->nb_rsp_cap * sizeof(char *),
8290 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008291 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008292
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008293 switch (curproxy->load_server_state_from_file) {
8294 case PR_SRV_STATE_FILE_UNSPEC:
8295 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8296 break;
8297 case PR_SRV_STATE_FILE_GLOBAL:
8298 if (!global.server_state_file) {
8299 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",
8300 curproxy->id);
8301 err_code |= ERR_WARN;
8302 }
8303 break;
8304 }
8305
Willy Tarreaubaaee002006-06-26 02:48:02 +02008306 /* first, we will invert the servers list order */
8307 newsrv = NULL;
8308 while (curproxy->srv) {
8309 struct server *next;
8310
8311 next = curproxy->srv->next;
8312 curproxy->srv->next = newsrv;
8313 newsrv = curproxy->srv;
8314 if (!next)
8315 break;
8316 curproxy->srv = next;
8317 }
8318
Willy Tarreau17edc812014-01-03 12:14:34 +01008319 /* Check that no server name conflicts. This causes trouble in the stats.
8320 * We only emit a warning for the first conflict affecting each server,
8321 * in order to avoid combinatory explosion if all servers have the same
8322 * name. We do that only for servers which do not have an explicit ID,
8323 * because these IDs were made also for distinguishing them and we don't
8324 * want to annoy people who correctly manage them.
8325 */
8326 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8327 struct server *other_srv;
8328
8329 if (newsrv->puid)
8330 continue;
8331
8332 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8333 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8334 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8335 newsrv->conf.file, newsrv->conf.line,
8336 proxy_type_str(curproxy), curproxy->id,
8337 newsrv->id, other_srv->conf.line);
8338 break;
8339 }
8340 }
8341 }
8342
Willy Tarreaudd701652010-05-25 23:03:02 +02008343 /* assign automatic UIDs to servers which don't have one yet */
8344 next_id = 1;
8345 newsrv = curproxy->srv;
8346 while (newsrv != NULL) {
8347 if (!newsrv->puid) {
8348 /* server ID not set, use automatic numbering with first
8349 * spare entry starting with next_svid.
8350 */
8351 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8352 newsrv->conf.id.key = newsrv->puid = next_id;
8353 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8354 }
8355 next_id++;
8356 newsrv = newsrv->next;
8357 }
8358
Willy Tarreau20697042007-11-15 23:26:18 +01008359 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008360 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008361
Willy Tarreau62c3be22012-01-20 13:12:32 +01008362 /*
8363 * If this server supports a maxconn parameter, it needs a dedicated
8364 * tasks to fill the emptied slots when a connection leaves.
8365 * Also, resolve deferred tracking dependency if needed.
8366 */
8367 newsrv = curproxy->srv;
8368 while (newsrv != NULL) {
8369 if (newsrv->minconn > newsrv->maxconn) {
8370 /* Only 'minconn' was specified, or it was higher than or equal
8371 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8372 * this will avoid further useless expensive computations.
8373 */
8374 newsrv->maxconn = newsrv->minconn;
8375 } else if (newsrv->maxconn && !newsrv->minconn) {
8376 /* minconn was not specified, so we set it to maxconn */
8377 newsrv->minconn = newsrv->maxconn;
8378 }
8379
Willy Tarreau17d45382016-12-22 21:16:08 +01008380 /* this will also properly set the transport layer for prod and checks */
8381 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8382 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8383 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8384 }
Emeric Brun94324a42012-10-11 14:00:19 +02008385
Willy Tarreau2f075e92013-12-03 11:11:34 +01008386 /* set the check type on the server */
8387 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8388
Willy Tarreau62c3be22012-01-20 13:12:32 +01008389 if (newsrv->trackit) {
8390 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008391 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008392 char *pname, *sname;
8393
8394 pname = newsrv->trackit;
8395 sname = strrchr(pname, '/');
8396
8397 if (sname)
8398 *sname++ = '\0';
8399 else {
8400 sname = pname;
8401 pname = NULL;
8402 }
8403
8404 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008405 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008406 if (!px) {
8407 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8408 proxy_type_str(curproxy), curproxy->id,
8409 newsrv->id, pname);
8410 cfgerr++;
8411 goto next_srv;
8412 }
8413 } else
8414 px = curproxy;
8415
8416 srv = findserver(px, sname);
8417 if (!srv) {
8418 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8419 proxy_type_str(curproxy), curproxy->id,
8420 newsrv->id, sname);
8421 cfgerr++;
8422 goto next_srv;
8423 }
8424
Willy Tarreau32091232014-05-16 13:52:00 +02008425 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8426 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8427 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008428 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008429 "tracking as it does not have any check nor agent enabled.\n",
8430 proxy_type_str(curproxy), curproxy->id,
8431 newsrv->id, px->id, srv->id);
8432 cfgerr++;
8433 goto next_srv;
8434 }
8435
8436 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8437
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008438 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008439 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8440 "belongs to a tracking chain looping back to %s/%s.\n",
8441 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008442 newsrv->id, px->id, srv->id, px->id,
8443 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008444 cfgerr++;
8445 goto next_srv;
8446 }
8447
8448 if (curproxy != px &&
8449 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8450 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8451 "tracking: disable-on-404 option inconsistency.\n",
8452 proxy_type_str(curproxy), curproxy->id,
8453 newsrv->id, px->id, srv->id);
8454 cfgerr++;
8455 goto next_srv;
8456 }
8457
Willy Tarreau62c3be22012-01-20 13:12:32 +01008458 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008459 newsrv->tracknext = srv->trackers;
8460 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008461
8462 free(newsrv->trackit);
8463 newsrv->trackit = NULL;
8464 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008465
8466 /*
8467 * resolve server's resolvers name and update the resolvers pointer
8468 * accordingly
8469 */
8470 if (newsrv->resolvers_id) {
8471 struct dns_resolvers *curr_resolvers;
8472 int found;
8473
8474 found = 0;
8475 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8476 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8477 found = 1;
8478 break;
8479 }
8480 }
8481
8482 if (!found) {
8483 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8484 proxy_type_str(curproxy), curproxy->id,
8485 newsrv->id, newsrv->resolvers_id);
8486 cfgerr++;
8487 } else {
8488 free(newsrv->resolvers_id);
8489 newsrv->resolvers_id = NULL;
8490 if (newsrv->resolution)
8491 newsrv->resolution->resolvers = curr_resolvers;
8492 }
8493 }
8494 else {
8495 /* if no resolvers section associated to this server
8496 * we can clean up the associated resolution structure
8497 */
8498 if (newsrv->resolution) {
8499 free(newsrv->resolution->hostname_dn);
8500 newsrv->resolution->hostname_dn = NULL;
8501 free(newsrv->resolution);
8502 newsrv->resolution = NULL;
8503 }
8504 }
8505
Willy Tarreau62c3be22012-01-20 13:12:32 +01008506 next_srv:
8507 newsrv = newsrv->next;
8508 }
8509
Olivier Houchard4e694042017-03-14 20:01:29 +01008510 /*
8511 * Try to generate dynamic cookies for servers now.
8512 * It couldn't be done earlier, since at the time we parsed
8513 * the server line, we may not have known yet that we
8514 * should use dynamic cookies, or the secret key may not
8515 * have been provided yet.
8516 */
8517 if (curproxy->ck_opts & PR_CK_DYNAMIC) {
8518 newsrv = curproxy->srv;
8519 while (newsrv != NULL) {
8520 srv_set_dyncookie(newsrv);
8521 newsrv = newsrv->next;
8522 }
8523
8524 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008525 /* We have to initialize the server lookup mechanism depending
8526 * on what LB algorithm was choosen.
8527 */
8528
8529 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8530 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8531 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008532 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8533 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8534 init_server_map(curproxy);
8535 } else {
8536 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8537 fwrr_init_server_groups(curproxy);
8538 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008539 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008540
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008541 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008542 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8543 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8544 fwlc_init_server_tree(curproxy);
8545 } else {
8546 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8547 fas_init_server_tree(curproxy);
8548 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008549 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008550
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008551 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008552 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8553 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8554 chash_init_server_tree(curproxy);
8555 } else {
8556 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8557 init_server_map(curproxy);
8558 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008559 break;
8560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008561
8562 if (curproxy->options & PR_O_LOGASAP)
8563 curproxy->to_log &= ~LW_BYTES;
8564
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008565 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008566 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8567 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008568 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8569 proxy_type_str(curproxy), curproxy->id);
8570 err_code |= ERR_WARN;
8571 }
8572
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008573 if (curproxy->mode != PR_MODE_HTTP) {
8574 int optnum;
8575
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008576 if (curproxy->uri_auth) {
8577 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8578 proxy_type_str(curproxy), curproxy->id);
8579 err_code |= ERR_WARN;
8580 curproxy->uri_auth = NULL;
8581 }
8582
Willy Tarreaude7dc882017-03-10 11:49:21 +01008583 if (curproxy->capture_name) {
8584 Warning("config : 'capture' statement ignored for %s '%s' as it requires HTTP mode.\n",
8585 proxy_type_str(curproxy), curproxy->id);
8586 err_code |= ERR_WARN;
8587 }
8588
8589 if (!LIST_ISEMPTY(&curproxy->http_req_rules)) {
8590 Warning("config : 'http-request' rules ignored for %s '%s' as they require HTTP mode.\n",
8591 proxy_type_str(curproxy), curproxy->id);
8592 err_code |= ERR_WARN;
8593 }
8594
8595 if (!LIST_ISEMPTY(&curproxy->http_res_rules)) {
8596 Warning("config : 'http-response' rules ignored for %s '%s' as they require HTTP mode.\n",
8597 proxy_type_str(curproxy), curproxy->id);
8598 err_code |= ERR_WARN;
8599 }
8600
8601 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8602 Warning("config : 'block' rules ignored for %s '%s' as they require HTTP mode.\n",
8603 proxy_type_str(curproxy), curproxy->id);
8604 err_code |= ERR_WARN;
8605 }
8606
8607 if (!LIST_ISEMPTY(&curproxy->redirect_rules)) {
8608 Warning("config : 'redirect' rules ignored for %s '%s' as they require HTTP mode.\n",
8609 proxy_type_str(curproxy), curproxy->id);
8610 err_code |= ERR_WARN;
8611 }
8612
Willy Tarreau87cf5142011-08-19 22:57:24 +02008613 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008614 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8615 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8616 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008617 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008618 }
8619
8620 if (curproxy->options & PR_O_ORGTO) {
8621 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8622 "originalto", proxy_type_str(curproxy), curproxy->id);
8623 err_code |= ERR_WARN;
8624 curproxy->options &= ~PR_O_ORGTO;
8625 }
8626
8627 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8628 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8629 (curproxy->cap & cfg_opts[optnum].cap) &&
8630 (curproxy->options & cfg_opts[optnum].val)) {
8631 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8632 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8633 err_code |= ERR_WARN;
8634 curproxy->options &= ~cfg_opts[optnum].val;
8635 }
8636 }
8637
8638 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8639 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8640 (curproxy->cap & cfg_opts2[optnum].cap) &&
8641 (curproxy->options2 & cfg_opts2[optnum].val)) {
8642 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8643 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8644 err_code |= ERR_WARN;
8645 curproxy->options2 &= ~cfg_opts2[optnum].val;
8646 }
8647 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008648
Willy Tarreau29fbe512015-08-20 19:35:14 +02008649#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008650 if (curproxy->conn_src.bind_hdr_occ) {
8651 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008652 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008653 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008654 err_code |= ERR_WARN;
8655 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008656#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008657 }
8658
Willy Tarreaubaaee002006-06-26 02:48:02 +02008659 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008660 * ensure that we're not cross-dressing a TCP server into HTTP.
8661 */
8662 newsrv = curproxy->srv;
8663 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008664 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008665 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8666 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008667 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008668 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008669
Willy Tarreau0cec3312011-10-31 13:49:26 +01008670 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8671 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8672 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8673 err_code |= ERR_WARN;
8674 }
8675
Willy Tarreauc93cd162014-05-13 15:54:22 +02008676 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008677 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8678 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8679 err_code |= ERR_WARN;
8680 }
8681
Willy Tarreau29fbe512015-08-20 19:35:14 +02008682#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008683 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8684 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008685 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 +01008686 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008687 err_code |= ERR_WARN;
8688 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008689#endif
Willy Tarreau4c183462017-01-06 12:21:38 +01008690
8691 if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
8692 if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8693 (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
8694 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
8695 (newsrv->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP) {
8696 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",
8697 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8698 err_code |= ERR_WARN;
8699 }
8700
8701
8702 if (newsrv->pp_opts & (SRV_PP_V1|SRV_PP_V2)) {
8703 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",
8704 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8705 err_code |= ERR_WARN;
8706 }
8707 }
8708
Willy Tarreau21d2af32008-02-14 20:25:24 +01008709 newsrv = newsrv->next;
8710 }
8711
Willy Tarreaue42bd962014-09-16 16:21:19 +02008712 /* check if we have a frontend with "tcp-request content" looking at L7
8713 * with no inspect-delay
8714 */
8715 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8716 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008717 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008718 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008719 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008720 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008721 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008722 break;
8723 }
8724
8725 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8726 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8727 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8728 " This means that these rules will randomly find their contents. This can be fixed by"
8729 " setting the tcp-request inspect-delay.\n",
8730 proxy_type_str(curproxy), curproxy->id);
8731 err_code |= ERR_WARN;
8732 }
8733 }
8734
Christopher Fauletd7c91962015-04-30 11:48:27 +02008735 /* Check filter configuration, if any */
8736 cfgerr += flt_check(curproxy);
8737
Willy Tarreauc1a21672009-08-16 22:37:44 +02008738 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008739 if (!curproxy->accept)
8740 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008741
Willy Tarreauc1a21672009-08-16 22:37:44 +02008742 if (curproxy->tcp_req.inspect_delay ||
8743 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008744 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008745
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008746 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008747 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008748 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008749 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008750
8751 /* both TCP and HTTP must check switching rules */
8752 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008753
8754 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008755 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008756 curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8757 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 +01008758 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008759 curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8760 curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008761 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008762 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008763 }
8764
8765 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008766 if (curproxy->tcp_req.inspect_delay ||
8767 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8768 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8769
Emeric Brun97679e72010-09-23 17:56:44 +02008770 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8771 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8772
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008773 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008774 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008775 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008776 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008777
8778 /* If the backend does requires RDP cookie persistence, we have to
8779 * enable the corresponding analyser.
8780 */
8781 if (curproxy->options2 & PR_O2_RDPC_PRST)
8782 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008783
8784 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008785 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008786 curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
8787 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 +01008788 if (curproxy->mode == PR_MODE_HTTP) {
Christopher Faulet0184ea72017-01-05 14:06:34 +01008789 curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
8790 curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
Christopher Faulet309c6412015-12-02 09:57:32 +01008791 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008792 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008793 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008794 }
8795
8796 /***********************************************************/
8797 /* At this point, target names have already been resolved. */
8798 /***********************************************************/
8799
8800 /* Check multi-process mode compatibility */
8801
8802 if (global.nbproc > 1 && global.stats_fe) {
8803 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8804 unsigned long mask;
8805
8806 mask = nbits(global.nbproc);
8807 if (global.stats_fe->bind_proc)
8808 mask &= global.stats_fe->bind_proc;
8809
8810 if (bind_conf->bind_proc)
8811 mask &= bind_conf->bind_proc;
8812
8813 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008814 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008815 break;
8816 }
8817 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8818 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");
8819 }
8820 }
8821
8822 /* Make each frontend inherit bind-process from its listeners when not specified. */
8823 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8824 if (curproxy->bind_proc)
8825 continue;
8826
8827 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8828 unsigned long mask;
8829
Willy Tarreaue428b082015-05-04 21:57:58 +02008830 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008831 curproxy->bind_proc |= mask;
8832 }
8833
8834 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008835 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008836 }
8837
8838 if (global.stats_fe) {
8839 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8840 unsigned long mask;
8841
Cyril Bonté06181952016-02-24 00:14:54 +01008842 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008843 global.stats_fe->bind_proc |= mask;
8844 }
8845 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008846 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008847 }
8848
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008849 /* propagate bindings from frontends to backends. Don't do it if there
8850 * are any fatal errors as we must not call it with unresolved proxies.
8851 */
8852 if (!cfgerr) {
8853 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8854 if (curproxy->cap & PR_CAP_FE)
8855 propagate_processes(curproxy, NULL);
8856 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008857 }
8858
8859 /* Bind each unbound backend to all processes when not specified. */
8860 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8861 if (curproxy->bind_proc)
8862 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008863 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008864 }
8865
8866 /*******************************************************/
8867 /* At this step, all proxies have a non-null bind_proc */
8868 /*******************************************************/
8869
8870 /* perform the final checks before creating tasks */
8871
8872 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8873 struct listener *listener;
8874 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008875
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008876 /* Configure SSL for each bind line.
8877 * Note: if configuration fails at some point, the ->ctx member
8878 * remains NULL so that listeners can later detach.
8879 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008880 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau55d37912016-12-21 23:38:39 +01008881 if (bind_conf->xprt->prepare_bind_conf &&
8882 bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008883 cfgerr++;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008884 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008885
Willy Tarreaue6b98942007-10-29 01:09:36 +01008886 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008887 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008888 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008889 int nbproc;
8890
8891 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008892 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008893 nbits(global.nbproc));
8894
8895 if (!nbproc) /* no intersection between listener and frontend */
8896 nbproc = 1;
8897
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008898 if (!listener->luid) {
8899 /* listener ID not set, use automatic numbering with first
8900 * spare entry starting with next_luid.
8901 */
8902 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8903 listener->conf.id.key = listener->luid = next_id;
8904 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008905 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008906 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008907
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008908 /* enable separate counters */
8909 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Willy Tarreauae9bea02016-11-25 14:44:52 +01008910 listener->counters = calloc(1, sizeof(*listener->counters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008911 if (!listener->name)
8912 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008913 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008914
Willy Tarreaue6b98942007-10-29 01:09:36 +01008915 if (curproxy->options & PR_O_TCP_NOLING)
8916 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008917 if (!listener->maxconn)
8918 listener->maxconn = curproxy->maxconn;
8919 if (!listener->backlog)
8920 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008921 if (!listener->maxaccept)
8922 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8923
8924 /* we want to have an optimal behaviour on single process mode to
8925 * maximize the work at once, but in multi-process we want to keep
8926 * some fairness between processes, so we target half of the max
8927 * number of events to be balanced over all the processes the proxy
8928 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8929 * used to disable the limit.
8930 */
8931 if (listener->maxaccept > 0) {
8932 if (nbproc > 1)
8933 listener->maxaccept = (listener->maxaccept + 1) / 2;
8934 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8935 }
8936
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008937 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008938 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008939 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008940 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008941
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008942 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008943 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008944
Willy Tarreau620408f2016-10-21 16:37:51 +02008945 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8946 listener->options |= LI_O_TCP_L5_RULES;
8947
Willy Tarreaude3041d2010-05-31 10:56:17 +02008948 if (curproxy->mon_mask.s_addr)
8949 listener->options |= LI_O_CHK_MONNET;
8950
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008951 /* smart accept mode is automatic in HTTP mode */
8952 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008953 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008954 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8955 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008956 }
8957
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008958 /* Release unused SSL configs */
8959 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01008960 if (!bind_conf->is_ssl && bind_conf->xprt->destroy_bind_conf)
8961 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008962 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008963
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008964 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008965 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008966 int count, maxproc = 0;
8967
8968 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008969 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008970 if (count > maxproc)
8971 maxproc = count;
8972 }
8973 /* backends have 0, frontends have 1 or more */
8974 if (maxproc != 1)
8975 Warning("Proxy '%s': in multi-process mode, stats will be"
8976 " limited to process assigned to the current request.\n",
8977 curproxy->id);
8978
Willy Tarreau102df612014-05-07 23:56:38 +02008979 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8980 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8981 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008982 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008983 }
Willy Tarreau102df612014-05-07 23:56:38 +02008984 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8985 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8986 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008987 }
8988 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008989
8990 /* create the task associated with the proxy */
8991 curproxy->task = task_new();
8992 if (curproxy->task) {
8993 curproxy->task->context = curproxy;
8994 curproxy->task->process = manage_proxy;
8995 /* no need to queue, it will be done automatically if some
8996 * listener gets limited.
8997 */
8998 curproxy->task->expire = TICK_ETERNITY;
8999 } else {
9000 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
9001 curproxy->id);
9002 cfgerr++;
9003 }
Willy Tarreaub369a042014-09-16 13:21:03 +02009004 }
9005
Willy Tarreaufbb78422011-06-05 15:38:35 +02009006 /* automatically compute fullconn if not set. We must not do it in the
9007 * loop above because cross-references are not yet fully resolved.
9008 */
9009 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9010 /* If <fullconn> is not set, let's set it to 10% of the sum of
9011 * the possible incoming frontend's maxconns.
9012 */
9013 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009014 /* we have the sum of the maxconns in <total>. We only
9015 * keep 10% of that sum to set the default fullconn, with
9016 * a hard minimum of 1 (to avoid a divide by zero).
9017 */
Emeric Brun3f783572017-01-12 11:21:28 +01009018 curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009019 if (!curproxy->fullconn)
9020 curproxy->fullconn = 1;
9021 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009022 }
9023
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009024 /*
9025 * Recount currently required checks.
9026 */
9027
9028 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9029 int optnum;
9030
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009031 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9032 if (curproxy->options & cfg_opts[optnum].val)
9033 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009034
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009035 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9036 if (curproxy->options2 & cfg_opts2[optnum].val)
9037 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009038 }
9039
Willy Tarreau0fca4832015-05-01 19:12:05 +02009040 /* compute the required process bindings for the peers */
9041 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9042 if (curproxy->table.peers.p)
9043 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9044
Willy Tarreau122541c2011-09-07 21:24:49 +02009045 if (peers) {
9046 struct peers *curpeers = peers, **last;
9047 struct peer *p, *pb;
9048
Willy Tarreau1e273012015-05-01 19:15:17 +02009049 /* Remove all peers sections which don't have a valid listener,
9050 * which are not used by any table, or which are bound to more
9051 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009052 */
9053 last = &peers;
9054 while (*last) {
9055 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009056
9057 if (curpeers->state == PR_STSTOPPED) {
9058 /* the "disabled" keyword was present */
9059 if (curpeers->peers_fe)
9060 stop_proxy(curpeers->peers_fe);
9061 curpeers->peers_fe = NULL;
9062 }
9063 else if (!curpeers->peers_fe) {
9064 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9065 curpeers->id, localpeer);
9066 }
David Carliere6c39412015-07-02 07:00:17 +00009067 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009068 /* either it's totally stopped or too much used */
9069 if (curpeers->peers_fe->bind_proc) {
9070 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009071 "running in different processes (%d different ones). "
9072 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009073 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009074 cfgerr++;
9075 }
9076 stop_proxy(curpeers->peers_fe);
9077 curpeers->peers_fe = NULL;
9078 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009079 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009080 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009081 last = &curpeers->next;
9082 continue;
9083 }
9084
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009085 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009086 p = curpeers->remote;
9087 while (p) {
9088 pb = p->next;
9089 free(p->id);
9090 free(p);
9091 p = pb;
9092 }
9093
9094 /* Destroy and unlink this curpeers section.
9095 * Note: curpeers is backed up into *last.
9096 */
9097 free(curpeers->id);
9098 curpeers = curpeers->next;
9099 free(*last);
9100 *last = curpeers;
9101 }
9102 }
9103
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009104 /* initialize stick-tables on backend capable proxies. This must not
9105 * be done earlier because the data size may be discovered while parsing
9106 * other proxies.
9107 */
9108 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9109 if (curproxy->state == PR_STSTOPPED)
9110 continue;
9111
9112 if (!stktable_init(&curproxy->table)) {
9113 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9114 cfgerr++;
9115 }
9116 }
9117
Simon Horman0d16a402015-01-30 11:22:58 +09009118 if (mailers) {
9119 struct mailers *curmailers = mailers, **last;
9120 struct mailer *m, *mb;
9121
9122 /* Remove all mailers sections which don't have a valid listener.
9123 * This can happen when a mailers section is never referenced.
9124 */
9125 last = &mailers;
9126 while (*last) {
9127 curmailers = *last;
9128 if (curmailers->users) {
9129 last = &curmailers->next;
9130 continue;
9131 }
9132
9133 Warning("Removing incomplete section 'mailers %s'.\n",
9134 curmailers->id);
9135
9136 m = curmailers->mailer_list;
9137 while (m) {
9138 mb = m->next;
9139 free(m->id);
9140 free(m);
9141 m = mb;
9142 }
9143
9144 /* Destroy and unlink this curmailers section.
9145 * Note: curmailers is backed up into *last.
9146 */
9147 free(curmailers->id);
9148 curmailers = curmailers->next;
9149 free(*last);
9150 *last = curmailers;
9151 }
9152 }
9153
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009154 /* Update server_state_file_name to backend name if backend is supposed to use
9155 * a server-state file locally defined and none has been provided */
9156 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9157 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9158 curproxy->server_state_file_name == NULL)
9159 curproxy->server_state_file_name = strdup(curproxy->id);
9160 }
9161
Willy Tarreau34eb6712011-10-24 18:15:04 +02009162 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009163 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009164 MEM_F_SHARED);
9165
Willy Tarreaubb925012009-07-23 13:36:36 +02009166 if (cfgerr > 0)
9167 err_code |= ERR_ALERT | ERR_FATAL;
9168 out:
9169 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009170}
9171
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009172/*
9173 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9174 * parsing sessions.
9175 */
9176void cfg_register_keywords(struct cfg_kw_list *kwl)
9177{
9178 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9179}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009180
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009181/*
9182 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9183 */
9184void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9185{
9186 LIST_DEL(&kwl->list);
9187 LIST_INIT(&kwl->list);
9188}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009189
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009190/* this function register new section in the haproxy configuration file.
9191 * <section_name> is the name of this new section and <section_parser>
9192 * is the called parser. If two section declaration have the same name,
9193 * only the first declared is used.
9194 */
9195int cfg_register_section(char *section_name,
9196 int (*section_parser)(const char *, int, char **, int))
9197{
9198 struct cfg_section *cs;
9199
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009200 list_for_each_entry(cs, &sections, list) {
9201 if (strcmp(cs->section_name, section_name) == 0) {
9202 Alert("register section '%s': already registered.\n", section_name);
9203 return 0;
9204 }
9205 }
9206
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009207 cs = calloc(1, sizeof(*cs));
9208 if (!cs) {
9209 Alert("register section '%s': out of memory.\n", section_name);
9210 return 0;
9211 }
9212
9213 cs->section_name = section_name;
9214 cs->section_parser = section_parser;
9215
9216 LIST_ADDQ(&sections, &cs->list);
9217
9218 return 1;
9219}
9220
Willy Tarreaubaaee002006-06-26 02:48:02 +02009221/*
David Carlier845efb52015-09-25 11:49:18 +01009222 * free all config section entries
9223 */
9224void cfg_unregister_sections(void)
9225{
9226 struct cfg_section *cs, *ics;
9227
9228 list_for_each_entry_safe(cs, ics, &sections, list) {
9229 LIST_DEL(&cs->list);
9230 free(cs);
9231 }
9232}
9233
Christopher Faulet7110b402016-10-26 11:09:44 +02009234void cfg_backup_sections(struct list *backup_sections)
9235{
9236 struct cfg_section *cs, *ics;
9237
9238 list_for_each_entry_safe(cs, ics, &sections, list) {
9239 LIST_DEL(&cs->list);
9240 LIST_ADDQ(backup_sections, &cs->list);
9241 }
9242}
9243
9244void cfg_restore_sections(struct list *backup_sections)
9245{
9246 struct cfg_section *cs, *ics;
9247
9248 list_for_each_entry_safe(cs, ics, backup_sections, list) {
9249 LIST_DEL(&cs->list);
9250 LIST_ADDQ(&sections, &cs->list);
9251 }
9252}
9253
Willy Tarreau659fbf02016-05-26 17:55:28 +02009254__attribute__((constructor))
9255static void cfgparse_init(void)
9256{
9257 /* Register internal sections */
9258 cfg_register_section("listen", cfg_parse_listen);
9259 cfg_register_section("frontend", cfg_parse_listen);
9260 cfg_register_section("backend", cfg_parse_listen);
9261 cfg_register_section("defaults", cfg_parse_listen);
9262 cfg_register_section("global", cfg_parse_global);
9263 cfg_register_section("userlist", cfg_parse_users);
9264 cfg_register_section("peers", cfg_parse_peers);
9265 cfg_register_section("mailers", cfg_parse_mailers);
9266 cfg_register_section("namespace_list", cfg_parse_netns);
9267 cfg_register_section("resolvers", cfg_parse_resolvers);
9268}
9269
David Carlier845efb52015-09-25 11:49:18 +01009270/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009271 * Local variables:
9272 * c-indent-level: 8
9273 * c-basic-offset: 8
9274 * End:
9275 */