blob: 4c0e2d4f0ee43728948fc0fe36a6a60249d37227 [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 */
Frédéric Lécailleb82f7422017-04-13 18:24:23 +02002857 if (!strcmp(args[0], "server") ||
2858 !strcmp(args[0], "default-server") ||
2859 !strcmp(args[0], "server-template")) {
Willy Tarreau272adea2014-03-31 10:39:59 +02002860 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2861 if (err_code & ERR_FATAL)
2862 goto out;
2863 }
2864 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002865 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002866 int cur_arg;
2867
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 if (curproxy == &defproxy) {
2869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002873 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875
Willy Tarreau24709282013-03-10 21:32:12 +01002876 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002877 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002882
Willy Tarreaua261e9b2016-12-22 20:44:00 +01002883 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002884
2885 /* use default settings for unix sockets */
2886 bind_conf->ux.uid = global.unix_bind.ux.uid;
2887 bind_conf->ux.gid = global.unix_bind.ux.gid;
2888 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002889
2890 /* NOTE: the following line might create several listeners if there
2891 * are comma-separated IPs or port ranges. So all further processing
2892 * will have to be applied to all listeners created after last_listen.
2893 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002894 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2895 if (errmsg && *errmsg) {
2896 indent_msg(&errmsg, 2);
2897 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002898 }
2899 else
2900 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2901 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002905
Willy Tarreau4348fad2012-09-20 16:48:07 +02002906 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2907 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002908 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002909 }
2910
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002911 cur_arg = 2;
2912 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002913 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002914 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002915 char *err;
2916
Willy Tarreau26982662012-09-12 23:17:10 +02002917 kw = bind_find_kw(args[cur_arg]);
2918 if (kw) {
2919 char *err = NULL;
2920 int code;
2921
2922 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002923 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2924 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002925 cur_arg += 1 + kw->skip ;
2926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
2929
Willy Tarreau4348fad2012-09-20 16:48:07 +02002930 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002931 err_code |= code;
2932
2933 if (code) {
2934 if (err && *err) {
2935 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002936 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002937 }
2938 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002939 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2940 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002941 if (code & ERR_FATAL) {
2942 free(err);
2943 cur_arg += 1 + kw->skip;
2944 goto out;
2945 }
2946 }
2947 free(err);
2948 cur_arg += 1 + kw->skip;
2949 continue;
2950 }
2951
Willy Tarreau8638f482012-09-18 18:01:17 +02002952 err = NULL;
2953 if (!bind_dumped) {
2954 bind_dump_kws(&err);
2955 indent_msg(&err, 4);
2956 bind_dumped = 1;
2957 }
2958
2959 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2960 file, linenum, args[0], args[1], args[cur_arg],
2961 err ? " Registered keywords :" : "", err ? err : "");
2962 free(err);
2963
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002966 }
Willy Tarreau93893792009-07-23 13:19:11 +02002967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968 }
2969 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002970 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2972 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002978
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 /* flush useless bits */
2980 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002983 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002986
William Lallemanddf1425a2015-04-28 20:17:49 +02002987 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2988 goto out;
2989
Willy Tarreau1c47f852006-07-09 08:22:27 +02002990 if (!*args[1]) {
2991 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2992 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002995 }
2996
Willy Tarreaua534fea2008-08-03 12:19:50 +02002997 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002998 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002999 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003000 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003001 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3002
Willy Tarreau93893792009-07-23 13:19:11 +02003003 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003006 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3007 goto out;
3008
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3010 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3011 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3012 else {
3013 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
3017 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003018 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003019 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003020
3021 if (curproxy == &defproxy) {
3022 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3023 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003026 }
3027
William Lallemanddf1425a2015-04-28 20:17:49 +02003028 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3029 goto out;
3030
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003031 if (!*args[1]) {
3032 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003036 }
3037
3038 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003039 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003040 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003041
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003042 if (curproxy->uuid <= 0) {
3043 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003044 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003047 }
3048
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003049 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3050 if (node) {
3051 struct proxy *target = container_of(node, struct proxy, conf.id);
3052 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3053 file, linenum, proxy_type_str(curproxy), curproxy->id,
3054 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003059 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003060 else if (!strcmp(args[0], "description")) {
3061 int i, len=0;
3062 char *d;
3063
Cyril Bonté99ed3272010-01-24 23:29:44 +01003064 if (curproxy == &defproxy) {
3065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3066 file, linenum, args[0]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
3069 }
3070
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003071 if (!*args[1]) {
3072 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3073 file, linenum, args[0]);
3074 return -1;
3075 }
3076
Willy Tarreau348acfe2014-04-14 15:00:39 +02003077 for (i = 1; *args[i]; i++)
3078 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003079
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003080 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003081 curproxy->desc = d;
3082
Willy Tarreau348acfe2014-04-14 15:00:39 +02003083 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3084 for (i = 2; *args[i]; i++)
3085 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003086
3087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003089 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 curproxy->state = PR_STSTOPPED;
3092 }
3093 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003094 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 curproxy->state = PR_STNEW;
3097 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003098 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3099 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003100 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003101
3102 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003103 unsigned int low, high;
3104
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003105 if (strcmp(args[cur_arg], "all") == 0) {
3106 set = 0;
3107 break;
3108 }
3109 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003110 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003111 }
3112 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003113 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003114 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003115 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003116 char *dash = strchr(args[cur_arg], '-');
3117
3118 low = high = str2uic(args[cur_arg]);
3119 if (dash)
3120 high = str2uic(dash + 1);
3121
3122 if (high < low) {
3123 unsigned int swap = low;
3124 low = high;
3125 high = swap;
3126 }
3127
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003128 if (low < 1 || high > LONGBITS) {
3129 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3130 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003133 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003134 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003135 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003136 }
3137 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003138 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3139 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003142 }
3143 cur_arg++;
3144 }
3145 curproxy->bind_proc = set;
3146 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003147 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003148 if (curproxy == &defproxy) {
3149 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003152 }
3153
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003154 err = invalid_char(args[1]);
3155 if (err) {
3156 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3157 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003158 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1822e8c2017-04-12 18:54:00 +02003159 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003160 }
3161
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003162 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003163 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3164 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003167 }
Olivier Houchard4e694042017-03-14 20:01:29 +01003168 }
3169 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
3170
3171 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3172 err_code |= ERR_WARN;
3173
3174 if (*(args[1]) == 0) {
3175 Alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
3176 file, linenum, args[0]);
3177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
3179 }
3180 free(curproxy->dyncookie_key);
3181 curproxy->dyncookie_key = strdup(args[1]);
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003182 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3184 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185
Willy Tarreau977b8e42006-12-29 14:19:17 +01003186 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003188
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 if (*(args[1]) == 0) {
3190 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3191 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003195
Willy Tarreau67402132012-05-31 20:40:20 +02003196 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003197 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003198 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003199 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 curproxy->cookie_name = strdup(args[1]);
3201 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003202
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 cur_arg = 2;
3204 while (*(args[cur_arg])) {
3205 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003206 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003209 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003212 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
3214 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003215 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
3217 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003218 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003220 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003221 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003224 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003226 else if (!strcmp(args[cur_arg], "httponly")) {
3227 curproxy->ck_opts |= PR_CK_HTTPONLY;
3228 }
3229 else if (!strcmp(args[cur_arg], "secure")) {
3230 curproxy->ck_opts |= PR_CK_SECURE;
3231 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003232 else if (!strcmp(args[cur_arg], "domain")) {
3233 if (!*args[cur_arg + 1]) {
3234 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3235 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003238 }
3239
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003240 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003241 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003242 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3243 " dots nor does not start with a dot."
3244 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003245 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003246 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003247 }
3248
3249 err = invalid_domainchar(args[cur_arg + 1]);
3250 if (err) {
3251 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3252 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003255 }
3256
Willy Tarreau68a897b2009-12-03 23:28:34 +01003257 if (!curproxy->cookie_domain) {
3258 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3259 } else {
3260 /* one domain was already specified, add another one by
3261 * building the string which will be returned along with
3262 * the cookie.
3263 */
3264 char *new_ptr;
3265 int new_len = strlen(curproxy->cookie_domain) +
3266 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3267 new_ptr = malloc(new_len);
3268 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3269 free(curproxy->cookie_domain);
3270 curproxy->cookie_domain = new_ptr;
3271 }
Willy Tarreau31936852010-10-06 16:59:56 +02003272 cur_arg++;
3273 }
3274 else if (!strcmp(args[cur_arg], "maxidle")) {
3275 unsigned int maxidle;
3276 const char *res;
3277
3278 if (!*args[cur_arg + 1]) {
3279 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3280 file, linenum, args[cur_arg]);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283 }
3284
3285 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3286 if (res) {
3287 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3288 file, linenum, *res, args[cur_arg]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
3291 }
3292 curproxy->cookie_maxidle = maxidle;
3293 cur_arg++;
3294 }
3295 else if (!strcmp(args[cur_arg], "maxlife")) {
3296 unsigned int maxlife;
3297 const char *res;
3298
3299 if (!*args[cur_arg + 1]) {
3300 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3301 file, linenum, args[cur_arg]);
3302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
3304 }
3305
3306 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3307 if (res) {
3308 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3309 file, linenum, *res, args[cur_arg]);
3310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
3312 }
3313 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003314 cur_arg++;
3315 }
Olivier Houcharda5938f72017-03-15 15:12:06 +01003316 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
Olivier Houchard4e694042017-03-14 20:01:29 +01003317
3318 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
3319 err_code |= ERR_WARN;
3320 curproxy->ck_opts |= PR_CK_DYNAMIC;
3321 }
3322
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 else {
Olivier Houchard4e694042017-03-14 20:01:29 +01003324 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 +02003325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 }
3329 cur_arg++;
3330 }
Willy Tarreau67402132012-05-31 20:40:20 +02003331 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3333 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003334 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
3336
Willy Tarreau67402132012-05-31 20:40:20 +02003337 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3339 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003342
Willy Tarreau67402132012-05-31 20:40:20 +02003343 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003344 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3345 file, linenum);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003349 else if (!strcmp(args[0], "email-alert")) {
3350 if (*(args[1]) == 0) {
3351 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3352 file, linenum, args[0]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
3357 if (!strcmp(args[1], "from")) {
3358 if (*(args[1]) == 0) {
3359 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3360 file, linenum, args[1]);
3361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
3363 }
3364 free(curproxy->email_alert.from);
3365 curproxy->email_alert.from = strdup(args[2]);
3366 }
3367 else if (!strcmp(args[1], "mailers")) {
3368 if (*(args[1]) == 0) {
3369 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3370 file, linenum, args[1]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374 free(curproxy->email_alert.mailers.name);
3375 curproxy->email_alert.mailers.name = strdup(args[2]);
3376 }
3377 else if (!strcmp(args[1], "myhostname")) {
3378 if (*(args[1]) == 0) {
3379 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3380 file, linenum, args[1]);
3381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
3383 }
3384 free(curproxy->email_alert.myhostname);
3385 curproxy->email_alert.myhostname = strdup(args[2]);
3386 }
Simon Horman64e34162015-02-06 11:11:57 +09003387 else if (!strcmp(args[1], "level")) {
3388 curproxy->email_alert.level = get_log_level(args[2]);
3389 if (curproxy->email_alert.level < 0) {
3390 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3391 file, linenum, args[1], args[2]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395 }
Simon Horman9dc49962015-01-30 11:22:59 +09003396 else if (!strcmp(args[1], "to")) {
3397 if (*(args[1]) == 0) {
3398 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3399 file, linenum, args[1]);
3400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
3402 }
3403 free(curproxy->email_alert.to);
3404 curproxy->email_alert.to = strdup(args[2]);
3405 }
3406 else {
3407 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3408 file, linenum, args[1]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
Simon Horman64e34162015-02-06 11:11:57 +09003412 /* Indicate that the email_alert is at least partially configured */
3413 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003414 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003415 else if (!strcmp(args[0], "external-check")) {
3416 if (*(args[1]) == 0) {
3417 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3418 file, linenum, args[0]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422
3423 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003424 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003425 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003426 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003427 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3428 file, linenum, args[1]);
3429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
3431 }
3432 free(curproxy->check_command);
3433 curproxy->check_command = strdup(args[2]);
3434 }
3435 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003436 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003437 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003438 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003439 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3440 file, linenum, args[1]);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444 free(curproxy->check_path);
3445 curproxy->check_path = strdup(args[2]);
3446 }
3447 else {
3448 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3449 file, linenum, args[1]);
3450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
3452 }
3453 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003454 else if (!strcmp(args[0], "persist")) { /* persist */
3455 if (*(args[1]) == 0) {
3456 Alert("parsing [%s:%d] : missing persist method.\n",
3457 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003460 }
3461
3462 if (!strncmp(args[1], "rdp-cookie", 10)) {
3463 curproxy->options2 |= PR_O2_RDPC_PRST;
3464
Emeric Brunb982a3d2010-01-04 15:45:53 +01003465 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003466 const char *beg, *end;
3467
3468 beg = args[1] + 11;
3469 end = strchr(beg, ')');
3470
William Lallemanddf1425a2015-04-28 20:17:49 +02003471 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3472 goto out;
3473
Emeric Brun647caf12009-06-30 17:57:00 +02003474 if (!end || end == beg) {
3475 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3476 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003479 }
3480
3481 free(curproxy->rdp_cookie_name);
3482 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3483 curproxy->rdp_cookie_len = end-beg;
3484 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003485 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003486 free(curproxy->rdp_cookie_name);
3487 curproxy->rdp_cookie_name = strdup("msts");
3488 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3489 }
3490 else { /* syntax */
3491 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3492 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003495 }
3496 }
3497 else {
3498 Alert("parsing [%s:%d] : unknown persist method.\n",
3499 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003502 }
3503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003505 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
3508 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003509 else if (!strcmp(args[0], "load-server-state-from-file")) {
3510 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3511 err_code |= ERR_WARN;
3512 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3513 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3514 }
3515 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3516 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3517 }
3518 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3519 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3520 }
3521 else {
3522 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3523 file, linenum, args[0], args[1]);
3524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
3526 }
3527 }
3528 else if (!strcmp(args[0], "server-state-file-name")) {
3529 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3530 err_code |= ERR_WARN;
3531 if (*(args[1]) == 0) {
3532 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3533 file, linenum, args[0]);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
3537 else if (!strcmp(args[1], "use-backend-name"))
3538 curproxy->server_state_file_name = strdup(curproxy->id);
3539 else
3540 curproxy->server_state_file_name = strdup(args[1]);
3541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003543 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003545
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003547 if (curproxy == &defproxy) {
3548 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
3551 }
3552
William Lallemand1a748ae2015-05-19 16:37:23 +02003553 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3554 goto out;
3555
Willy Tarreaubaaee002006-06-26 02:48:02 +02003556 if (*(args[4]) == 0) {
3557 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3558 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003562 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 curproxy->capture_name = strdup(args[2]);
3564 curproxy->capture_namelen = strlen(curproxy->capture_name);
3565 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 curproxy->to_log |= LW_COOKIE;
3567 }
3568 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3569 struct cap_hdr *hdr;
3570
3571 if (curproxy == &defproxy) {
3572 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 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 }
3576
William Lallemand1a748ae2015-05-19 16:37:23 +02003577 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3578 goto out;
3579
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3581 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3582 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 }
3586
Vincent Bernat02779b62016-04-03 13:48:43 +02003587 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 hdr->next = curproxy->req_cap;
3589 hdr->name = strdup(args[3]);
3590 hdr->namelen = strlen(args[3]);
3591 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003592 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 hdr->index = curproxy->nb_req_cap++;
3594 curproxy->req_cap = hdr;
3595 curproxy->to_log |= LW_REQHDR;
3596 }
3597 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3598 struct cap_hdr *hdr;
3599
3600 if (curproxy == &defproxy) {
3601 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 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 }
3605
William Lallemand1a748ae2015-05-19 16:37:23 +02003606 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3607 goto out;
3608
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3610 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3611 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003615 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 hdr->next = curproxy->rsp_cap;
3617 hdr->name = strdup(args[3]);
3618 hdr->namelen = strlen(args[3]);
3619 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003620 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 hdr->index = curproxy->nb_rsp_cap++;
3622 curproxy->rsp_cap = hdr;
3623 curproxy->to_log |= LW_RSPHDR;
3624 }
3625 else {
3626 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3627 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 }
3631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003633 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003635
William Lallemanddf1425a2015-04-28 20:17:49 +02003636 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3637 goto out;
3638
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 if (*(args[1]) == 0) {
3640 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
3645 curproxy->conn_retries = atol(args[1]);
3646 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003647 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003648 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003649
3650 if (curproxy == &defproxy) {
3651 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
3654 }
3655
Willy Tarreau20b0de52012-12-24 15:45:22 +01003656 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003657 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003658 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3659 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3660 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3661 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003662 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 +01003663 file, linenum, args[0]);
3664 err_code |= ERR_WARN;
3665 }
3666
Willy Tarreauff011f22011-01-06 17:51:27 +01003667 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003668
Willy Tarreauff011f22011-01-06 17:51:27 +01003669 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003670 err_code |= ERR_ALERT | ERR_ABORT;
3671 goto out;
3672 }
3673
Willy Tarreau5002f572014-04-23 01:32:02 +02003674 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003675 err_code |= warnif_cond_conflicts(rule->cond,
3676 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3677 file, linenum);
3678
Willy Tarreauff011f22011-01-06 17:51:27 +01003679 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003680 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003681 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003682 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003683
3684 if (curproxy == &defproxy) {
3685 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
3689
3690 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003691 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003692 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3693 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003694 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3695 file, linenum, args[0]);
3696 err_code |= ERR_WARN;
3697 }
3698
3699 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3700
3701 if (!rule) {
3702 err_code |= ERR_ALERT | ERR_ABORT;
3703 goto out;
3704 }
3705
3706 err_code |= warnif_cond_conflicts(rule->cond,
3707 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3708 file, linenum);
3709
3710 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3711 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003712 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3713 /* set the header name and length into the proxy structure */
3714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3715 err_code |= ERR_WARN;
3716
3717 if (!*args[1]) {
3718 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3719 file, linenum, args[0]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723
3724 /* set the desired header name */
3725 free(curproxy->server_id_hdr_name);
3726 curproxy->server_id_hdr_name = strdup(args[1]);
3727 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3728 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003729 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003730 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003731
Willy Tarreaub099aca2008-10-12 17:26:37 +02003732 if (curproxy == &defproxy) {
3733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003736 }
3737
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003738 /* emulate "block" using "http-request block". Since these rules are supposed to
3739 * be processed before all http-request rules, we put them into their own list
3740 * and will insert them at the end.
3741 */
3742 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3743 if (!rule) {
3744 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003745 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003746 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003747 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3748 err_code |= warnif_cond_conflicts(rule->cond,
3749 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3750 file, linenum);
3751 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003752
3753 if (!already_warned(WARN_BLOCK_DEPRECATED))
3754 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]);
3755
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003756 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003757 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003758 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003759
Cyril Bonté99ed3272010-01-24 23:29:44 +01003760 if (curproxy == &defproxy) {
3761 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765
Willy Tarreaube4653b2015-05-28 15:26:58 +02003766 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003767 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3768 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003771 }
3772
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003773 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003774 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003775 err_code |= warnif_cond_conflicts(rule->cond,
3776 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3777 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003778 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003779 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003780 struct switching_rule *rule;
3781
Willy Tarreaub099aca2008-10-12 17:26:37 +02003782 if (curproxy == &defproxy) {
3783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003786 }
3787
Willy Tarreau55ea7572007-06-17 19:56:27 +02003788 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003790
3791 if (*(args[1]) == 0) {
3792 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003795 }
3796
Willy Tarreauf51658d2014-04-23 01:21:56 +02003797 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3798 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3799 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3800 file, linenum, errmsg);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003804
Willy Tarreauf51658d2014-04-23 01:21:56 +02003805 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003806 }
Willy Tarreau4f862642017-02-28 09:34:39 +01003807 else if (*args[2]) {
3808 Alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
3809 file, linenum, args[2]);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003813
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003814 rule = calloc(1, sizeof(*rule));
Thierry FOURNIER / OZON.IO5948b012016-11-24 23:58:32 +01003815 if (!rule) {
3816 Alert("Out of memory error.\n");
3817 goto out;
3818 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003819 rule->cond = cond;
3820 rule->be.name = strdup(args[1]);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01003821 rule->line = linenum;
3822 rule->file = strdup(file);
3823 if (!rule->file) {
3824 Alert("Out of memory error.\n");
3825 goto out;
3826 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003827 LIST_INIT(&rule->list);
3828 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3829 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003830 else if (strcmp(args[0], "use-server") == 0) {
3831 struct server_rule *rule;
3832
3833 if (curproxy == &defproxy) {
3834 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
3837 }
3838
3839 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3840 err_code |= ERR_WARN;
3841
3842 if (*(args[1]) == 0) {
3843 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847
3848 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3849 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3850 file, linenum, args[0]);
3851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
3853 }
3854
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003855 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3856 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3857 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003862 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003863
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003864 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003865 rule->cond = cond;
3866 rule->srv.name = strdup(args[1]);
3867 LIST_INIT(&rule->list);
3868 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3869 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3870 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003871 else if ((!strcmp(args[0], "force-persist")) ||
3872 (!strcmp(args[0], "ignore-persist"))) {
3873 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003874
3875 if (curproxy == &defproxy) {
3876 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
3879 }
3880
3881 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3882 err_code |= ERR_WARN;
3883
Willy Tarreauef6494c2010-01-28 17:12:36 +01003884 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003885 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3886 file, linenum, args[0]);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
3890
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003891 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3892 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3893 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
3896 }
3897
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003898 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3899 * where force-persist is applied.
3900 */
3901 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003902
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003903 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003904 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003905 if (!strcmp(args[0], "force-persist")) {
3906 rule->type = PERSIST_TYPE_FORCE;
3907 } else {
3908 rule->type = PERSIST_TYPE_IGNORE;
3909 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003910 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003911 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003912 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003913 else if (!strcmp(args[0], "stick-table")) {
3914 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003915 struct proxy *other;
3916
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003917 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003918 if (other) {
3919 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3920 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
3923 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003924
Emeric Brun32da3c42010-09-23 18:39:19 +02003925 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003926 curproxy->table.type = (unsigned int)-1;
3927 while (*args[myidx]) {
3928 const char *err;
3929
3930 if (strcmp(args[myidx], "size") == 0) {
3931 myidx++;
3932 if (!*(args[myidx])) {
3933 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3934 file, linenum, args[myidx-1]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3939 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3940 file, linenum, *err, args[myidx-1]);
3941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
3943 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003944 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003945 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003946 else if (strcmp(args[myidx], "peers") == 0) {
3947 myidx++;
Godbach50523162013-12-11 19:48:57 +08003948 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003949 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3950 file, linenum, args[myidx-1]);
3951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Godbach50523162013-12-11 19:48:57 +08003953 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003954 curproxy->table.peers.name = strdup(args[myidx++]);
3955 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003956 else if (strcmp(args[myidx], "expire") == 0) {
3957 myidx++;
3958 if (!*(args[myidx])) {
3959 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3960 file, linenum, args[myidx-1]);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
3964 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3965 if (err) {
3966 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3967 file, linenum, *err, args[myidx-1]);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003971 if (val > INT_MAX) {
3972 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3973 file, linenum, val);
3974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
3976 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003977 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003978 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003979 }
3980 else if (strcmp(args[myidx], "nopurge") == 0) {
3981 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003982 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003983 }
3984 else if (strcmp(args[myidx], "type") == 0) {
3985 myidx++;
3986 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3987 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3988 file, linenum, args[myidx]);
3989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
3991 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003992 /* myidx already points to next arg */
3993 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003994 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003995 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003996 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003997
3998 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003999 nw = args[myidx];
4000 while (*nw) {
4001 /* the "store" keyword supports a comma-separated list */
4002 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004003 sa = NULL; /* store arg */
4004 while (*nw && *nw != ',') {
4005 if (*nw == '(') {
4006 *nw = 0;
4007 sa = ++nw;
4008 while (*nw != ')') {
4009 if (!*nw) {
4010 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4011 file, linenum, args[0], cw);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
4015 nw++;
4016 }
4017 *nw = '\0';
4018 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004019 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004020 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004021 if (*nw)
4022 *nw++ = '\0';
4023 type = stktable_get_data_type(cw);
4024 if (type < 0) {
4025 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4026 file, linenum, args[0], cw);
4027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
4029 }
Willy Tarreauac782882010-06-20 10:41:54 +02004030
4031 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4032 switch (err) {
4033 case PE_NONE: break;
4034 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004035 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4036 file, linenum, args[0], cw);
4037 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004038 break;
4039
4040 case PE_ARG_MISSING:
4041 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4042 file, linenum, args[0], cw);
4043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
4045
4046 case PE_ARG_NOT_USED:
4047 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4048 file, linenum, args[0], cw);
4049 err_code |= ERR_ALERT | ERR_FATAL;
4050 goto out;
4051
4052 default:
4053 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4054 file, linenum, args[0], cw);
4055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004057 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004058 }
4059 myidx++;
4060 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004061 else {
4062 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4063 file, linenum, args[myidx]);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004066 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004067 }
4068
4069 if (!curproxy->table.size) {
4070 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4071 file, linenum);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075
4076 if (curproxy->table.type == (unsigned int)-1) {
4077 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4078 file, linenum);
4079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
4081 }
4082 }
4083 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004084 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004085 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004086 int myidx = 0;
4087 const char *name = NULL;
4088 int flags;
4089
4090 if (curproxy == &defproxy) {
4091 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095
4096 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4097 err_code |= ERR_WARN;
4098 goto out;
4099 }
4100
4101 myidx++;
4102 if ((strcmp(args[myidx], "store") == 0) ||
4103 (strcmp(args[myidx], "store-request") == 0)) {
4104 myidx++;
4105 flags = STK_IS_STORE;
4106 }
4107 else if (strcmp(args[myidx], "store-response") == 0) {
4108 myidx++;
4109 flags = STK_IS_STORE | STK_ON_RSP;
4110 }
4111 else if (strcmp(args[myidx], "match") == 0) {
4112 myidx++;
4113 flags = STK_IS_MATCH;
4114 }
4115 else if (strcmp(args[myidx], "on") == 0) {
4116 myidx++;
4117 flags = STK_IS_MATCH | STK_IS_STORE;
4118 }
4119 else {
4120 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
4123 }
4124
4125 if (*(args[myidx]) == 0) {
4126 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
4129 }
4130
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004131 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004132 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004134 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
4137 }
4138
4139 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004140 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4141 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4142 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004143 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004144 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004145 goto out;
4146 }
4147 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004148 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4149 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4150 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004151 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004152 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004153 goto out;
4154 }
4155 }
4156
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004157 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004158 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004159
Emeric Brunb982a3d2010-01-04 15:45:53 +01004160 if (strcmp(args[myidx], "table") == 0) {
4161 myidx++;
4162 name = args[myidx++];
4163 }
4164
Willy Tarreauef6494c2010-01-28 17:12:36 +01004165 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004166 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4167 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4168 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004169 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004170 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004171 goto out;
4172 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004173 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004174 else if (*(args[myidx])) {
4175 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4176 file, linenum, args[0], args[myidx]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004178 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004179 goto out;
4180 }
Emeric Brun97679e72010-09-23 17:56:44 +02004181 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004182 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004183 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004184 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004185
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004186 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004187 rule->cond = cond;
4188 rule->expr = expr;
4189 rule->flags = flags;
4190 rule->table.name = name ? strdup(name) : NULL;
4191 LIST_INIT(&rule->list);
4192 if (flags & STK_ON_RSP)
4193 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4194 else
4195 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 else if (!strcmp(args[0], "stats")) {
4198 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4199 curproxy->uri_auth = NULL; /* we must detach from the default config */
4200
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004201 if (!*args[1]) {
4202 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004203 } else if (!strcmp(args[1], "admin")) {
4204 struct stats_admin_rule *rule;
4205
4206 if (curproxy == &defproxy) {
4207 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
4211
4212 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4213 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4214 err_code |= ERR_ALERT | ERR_ABORT;
4215 goto out;
4216 }
4217
4218 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4219 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4220 file, linenum, args[0], args[1]);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004224 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4225 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4226 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
4230
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004231 err_code |= warnif_cond_conflicts(cond,
4232 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4233 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004234
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004235 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004236 rule->cond = cond;
4237 LIST_INIT(&rule->list);
4238 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004239 } else if (!strcmp(args[1], "uri")) {
4240 if (*(args[2]) == 0) {
4241 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4245 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_ABORT;
4247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004248 }
4249 } else if (!strcmp(args[1], "realm")) {
4250 if (*(args[2]) == 0) {
4251 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004254 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4255 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_ABORT;
4257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004259 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004260 unsigned interval;
4261
4262 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4263 if (err) {
4264 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4265 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004268 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4269 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004270 err_code |= ERR_ALERT | ERR_ABORT;
4271 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004272 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004273 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004274 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004275
4276 if (curproxy == &defproxy) {
4277 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
4280 }
4281
4282 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4283 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4284 err_code |= ERR_ALERT | ERR_ABORT;
4285 goto out;
4286 }
4287
Willy Tarreauff011f22011-01-06 17:51:27 +01004288 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004289 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004290 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4291 file, linenum, args[0]);
4292 err_code |= ERR_WARN;
4293 }
4294
Willy Tarreauff011f22011-01-06 17:51:27 +01004295 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004296
Willy Tarreauff011f22011-01-06 17:51:27 +01004297 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004298 err_code |= ERR_ALERT | ERR_ABORT;
4299 goto out;
4300 }
4301
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004302 err_code |= warnif_cond_conflicts(rule->cond,
4303 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4304 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004305 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004306
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 } else if (!strcmp(args[1], "auth")) {
4308 if (*(args[2]) == 0) {
4309 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4313 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_ABORT;
4315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 }
4317 } else if (!strcmp(args[1], "scope")) {
4318 if (*(args[2]) == 0) {
4319 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4323 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_ABORT;
4325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004326 }
4327 } else if (!strcmp(args[1], "enable")) {
4328 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4329 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004330 err_code |= ERR_ALERT | ERR_ABORT;
4331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004333 } else if (!strcmp(args[1], "hide-version")) {
4334 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4335 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_ABORT;
4337 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004338 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004339 } else if (!strcmp(args[1], "show-legends")) {
4340 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4341 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4342 err_code |= ERR_ALERT | ERR_ABORT;
4343 goto out;
4344 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004345 } else if (!strcmp(args[1], "show-node")) {
4346
4347 if (*args[2]) {
4348 int i;
4349 char c;
4350
4351 for (i=0; args[2][i]; i++) {
4352 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004353 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4354 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004355 break;
4356 }
4357
4358 if (!i || args[2][i]) {
4359 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4360 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4361 file, linenum, args[0], args[1]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365 }
4366
4367 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4368 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4369 err_code |= ERR_ALERT | ERR_ABORT;
4370 goto out;
4371 }
4372 } else if (!strcmp(args[1], "show-desc")) {
4373 char *desc = NULL;
4374
4375 if (*args[2]) {
4376 int i, len=0;
4377 char *d;
4378
Willy Tarreau348acfe2014-04-14 15:00:39 +02004379 for (i = 2; *args[i]; i++)
4380 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004381
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004382 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004383
Willy Tarreau348acfe2014-04-14 15:00:39 +02004384 d += snprintf(d, desc + len - d, "%s", args[2]);
4385 for (i = 3; *args[i]; i++)
4386 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004387 }
4388
4389 if (!*args[2] && !global.desc)
4390 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4391 file, linenum, args[1]);
4392 else {
4393 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4394 free(desc);
4395 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4396 err_code |= ERR_ALERT | ERR_ABORT;
4397 goto out;
4398 }
4399 free(desc);
4400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004402stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004403 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 +01004404 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 }
4408 }
4409 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004410 int optnum;
4411
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004412 if (*(args[1]) == '\0') {
4413 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4414 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004418
4419 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4420 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004421 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4422 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4423 file, linenum, cfg_opts[optnum].name);
4424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
4426 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004427 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4428 goto out;
4429
Willy Tarreau93893792009-07-23 13:19:11 +02004430 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4431 err_code |= ERR_WARN;
4432 goto out;
4433 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004434
Willy Tarreau3842f002009-06-14 11:39:52 +02004435 curproxy->no_options &= ~cfg_opts[optnum].val;
4436 curproxy->options &= ~cfg_opts[optnum].val;
4437
4438 switch (kwm) {
4439 case KWM_STD:
4440 curproxy->options |= cfg_opts[optnum].val;
4441 break;
4442 case KWM_NO:
4443 curproxy->no_options |= cfg_opts[optnum].val;
4444 break;
4445 case KWM_DEF: /* already cleared */
4446 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004447 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004448
Willy Tarreau93893792009-07-23 13:19:11 +02004449 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004450 }
4451 }
4452
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004453 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4454 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004455 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4456 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4457 file, linenum, cfg_opts2[optnum].name);
4458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
4460 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004461 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4462 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004463 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4464 err_code |= ERR_WARN;
4465 goto out;
4466 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004467
Willy Tarreau3842f002009-06-14 11:39:52 +02004468 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4469 curproxy->options2 &= ~cfg_opts2[optnum].val;
4470
4471 switch (kwm) {
4472 case KWM_STD:
4473 curproxy->options2 |= cfg_opts2[optnum].val;
4474 break;
4475 case KWM_NO:
4476 curproxy->no_options2 |= cfg_opts2[optnum].val;
4477 break;
4478 case KWM_DEF: /* already cleared */
4479 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004480 }
Willy Tarreau93893792009-07-23 13:19:11 +02004481 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004482 }
4483 }
4484
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004485 /* HTTP options override each other. They can be cancelled using
4486 * "no option xxx" which only switches to default mode if the mode
4487 * was this one (useful for cancelling options set in defaults
4488 * sections).
4489 */
4490 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004491 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4492 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004493 if (kwm == KWM_STD) {
4494 curproxy->options &= ~PR_O_HTTP_MODE;
4495 curproxy->options |= PR_O_HTTP_PCL;
4496 goto out;
4497 }
4498 else if (kwm == KWM_NO) {
4499 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4500 curproxy->options &= ~PR_O_HTTP_MODE;
4501 goto out;
4502 }
4503 }
4504 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004505 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4506 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004507 if (kwm == KWM_STD) {
4508 curproxy->options &= ~PR_O_HTTP_MODE;
4509 curproxy->options |= PR_O_HTTP_FCL;
4510 goto out;
4511 }
4512 else if (kwm == KWM_NO) {
4513 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4514 curproxy->options &= ~PR_O_HTTP_MODE;
4515 goto out;
4516 }
4517 }
4518 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004519 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4520 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004521 if (kwm == KWM_STD) {
4522 curproxy->options &= ~PR_O_HTTP_MODE;
4523 curproxy->options |= PR_O_HTTP_SCL;
4524 goto out;
4525 }
4526 else if (kwm == KWM_NO) {
4527 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4528 curproxy->options &= ~PR_O_HTTP_MODE;
4529 goto out;
4530 }
4531 }
4532 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004533 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4534 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004535 if (kwm == KWM_STD) {
4536 curproxy->options &= ~PR_O_HTTP_MODE;
4537 curproxy->options |= PR_O_HTTP_KAL;
4538 goto out;
4539 }
4540 else if (kwm == KWM_NO) {
4541 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4542 curproxy->options &= ~PR_O_HTTP_MODE;
4543 goto out;
4544 }
4545 }
4546 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004547 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4548 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004549 if (kwm == KWM_STD) {
4550 curproxy->options &= ~PR_O_HTTP_MODE;
4551 curproxy->options |= PR_O_HTTP_TUN;
4552 goto out;
4553 }
4554 else if (kwm == KWM_NO) {
4555 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4556 curproxy->options &= ~PR_O_HTTP_MODE;
4557 goto out;
4558 }
4559 }
4560
Joseph Lynch726ab712015-05-11 23:25:34 -07004561 /* Redispatch can take an integer argument that control when the
4562 * resispatch occurs. All values are relative to the retries option.
4563 * This can be cancelled using "no option xxx".
4564 */
4565 if (strcmp(args[1], "redispatch") == 0) {
4566 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4567 err_code |= ERR_WARN;
4568 goto out;
4569 }
4570
4571 curproxy->no_options &= ~PR_O_REDISP;
4572 curproxy->options &= ~PR_O_REDISP;
4573
4574 switch (kwm) {
4575 case KWM_STD:
4576 curproxy->options |= PR_O_REDISP;
4577 curproxy->redispatch_after = -1;
4578 if(*args[2]) {
4579 curproxy->redispatch_after = atol(args[2]);
4580 }
4581 break;
4582 case KWM_NO:
4583 curproxy->no_options |= PR_O_REDISP;
4584 curproxy->redispatch_after = 0;
4585 break;
4586 case KWM_DEF: /* already cleared */
4587 break;
4588 }
4589 goto out;
4590 }
4591
Willy Tarreau3842f002009-06-14 11:39:52 +02004592 if (kwm != KWM_STD) {
4593 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004594 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004597 }
4598
Emeric Brun3a058f32009-06-30 18:26:00 +02004599 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004600 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004602 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004603 if (*(args[2]) != '\0') {
4604 if (!strcmp(args[2], "clf")) {
4605 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004606 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004607 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004608 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_ALERT | ERR_FATAL;
4610 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004611 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004612 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4613 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004614 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004615 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4616 char *oldlogformat = "log-format";
4617 char *clflogformat = "";
4618
4619 if (curproxy->conf.logformat_string == default_http_log_format)
4620 oldlogformat = "option httplog";
4621 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4622 oldlogformat = "option tcplog";
4623 else if (curproxy->conf.logformat_string == clf_http_log_format)
4624 oldlogformat = "option httplog clf";
4625 if (logformat == clf_http_log_format)
4626 clflogformat = " clf";
4627 Warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
4628 file, linenum, clflogformat, oldlogformat);
4629 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004630 if (curproxy->conf.logformat_string != default_http_log_format &&
4631 curproxy->conf.logformat_string != default_tcp_log_format &&
4632 curproxy->conf.logformat_string != clf_http_log_format)
4633 free(curproxy->conf.logformat_string);
4634 curproxy->conf.logformat_string = logformat;
4635
4636 free(curproxy->conf.lfs_file);
4637 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4638 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004639 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004640 else if (!strcmp(args[1], "tcplog")) {
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02004641 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
4642 char *oldlogformat = "log-format";
4643
4644 if (curproxy->conf.logformat_string == default_http_log_format)
4645 oldlogformat = "option httplog";
4646 else if (curproxy->conf.logformat_string == default_tcp_log_format)
4647 oldlogformat = "option tcplog";
4648 else if (curproxy->conf.logformat_string == clf_http_log_format)
4649 oldlogformat = "option httplog clf";
4650 Warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
4651 file, linenum, oldlogformat);
4652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004653 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004654 if (curproxy->conf.logformat_string != default_http_log_format &&
4655 curproxy->conf.logformat_string != default_tcp_log_format &&
4656 curproxy->conf.logformat_string != clf_http_log_format)
4657 free(curproxy->conf.logformat_string);
4658 curproxy->conf.logformat_string = default_tcp_log_format;
4659
4660 free(curproxy->conf.lfs_file);
4661 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4662 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004663
4664 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4665 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004668 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004669 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004670 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004671
William Lallemanddf1425a2015-04-28 20:17:49 +02004672 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4673 goto out;
4674
Willy Tarreau13943ab2006-12-31 00:24:10 +01004675 if (curproxy->cap & PR_CAP_FE)
4676 curproxy->options |= PR_O_TCP_CLI_KA;
4677 if (curproxy->cap & PR_CAP_BE)
4678 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 }
4680 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004681 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004682 err_code |= ERR_WARN;
4683
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004685 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004686 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004687 curproxy->options2 &= ~PR_O2_CHK_ANY;
4688 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004689 if (!*args[2]) { /* no argument */
4690 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4691 curproxy->check_len = strlen(DEF_CHECK_REQ);
4692 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004693 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004694 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004696 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004698 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 if (*args[4])
4700 reqlen += strlen(args[4]);
4701 else
4702 reqlen += strlen("HTTP/1.0");
4703
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004704 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004706 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004708 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4709 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004710 }
4711 else if (!strcmp(args[1], "ssl-hello-chk")) {
4712 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004713 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004715
Willy Tarreaua534fea2008-08-03 12:19:50 +02004716 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004717 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004718 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004719 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004720
4721 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 }
Willy Tarreau23677902007-05-08 23:50:35 +02004724 else if (!strcmp(args[1], "smtpchk")) {
4725 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004726 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004727 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004728 curproxy->options2 &= ~PR_O2_CHK_ANY;
4729 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004730
4731 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4732 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4733 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4734 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4735 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4736 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004737 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004738 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4739 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4740 } else {
4741 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4742 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4743 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4744 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4745 }
4746 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004747 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4748 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004749 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004750 else if (!strcmp(args[1], "pgsql-check")) {
4751 /* use PostgreSQL request to check servers' health */
4752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4753 err_code |= ERR_WARN;
4754
4755 free(curproxy->check_req);
4756 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004757 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004758 curproxy->options2 |= PR_O2_PGSQL_CHK;
4759
4760 if (*(args[2])) {
4761 int cur_arg = 2;
4762
4763 while (*(args[cur_arg])) {
4764 if (strcmp(args[cur_arg], "user") == 0) {
4765 char * packet;
4766 uint32_t packet_len;
4767 uint32_t pv;
4768
4769 /* suboption header - needs additional argument for it */
4770 if (*(args[cur_arg+1]) == 0) {
4771 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4772 file, linenum, args[0], args[1], args[cur_arg]);
4773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
4775 }
4776
4777 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4778 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4779 pv = htonl(0x30000); /* protocol version 3.0 */
4780
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004781 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004782
4783 memcpy(packet + 4, &pv, 4);
4784
4785 /* copy "user" */
4786 memcpy(packet + 8, "user", 4);
4787
4788 /* copy username */
4789 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4790
4791 free(curproxy->check_req);
4792 curproxy->check_req = packet;
4793 curproxy->check_len = packet_len;
4794
4795 packet_len = htonl(packet_len);
4796 memcpy(packet, &packet_len, 4);
4797 cur_arg += 2;
4798 } else {
4799 /* unknown suboption - catchall */
4800 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4801 file, linenum, args[0], args[1]);
4802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
4804 }
4805 } /* end while loop */
4806 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004807 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4808 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004809 }
4810
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004811 else if (!strcmp(args[1], "redis-check")) {
4812 /* use REDIS PING request to check servers' health */
4813 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4814 err_code |= ERR_WARN;
4815
4816 free(curproxy->check_req);
4817 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004818 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004819 curproxy->options2 |= PR_O2_REDIS_CHK;
4820
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004821 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004822 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4823 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004824
4825 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4826 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004827 }
4828
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004829 else if (!strcmp(args[1], "mysql-check")) {
4830 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004831 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4832 err_code |= ERR_WARN;
4833
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004834 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004835 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004836 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004837 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004838
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004839 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004840 * const char mysql40_client_auth_pkt[] = {
4841 * "\x0e\x00\x00" // packet length
4842 * "\x01" // packet number
4843 * "\x00\x00" // client capabilities
4844 * "\x00\x00\x01" // max packet
4845 * "haproxy\x00" // username (null terminated string)
4846 * "\x00" // filler (always 0x00)
4847 * "\x01\x00\x00" // packet length
4848 * "\x00" // packet number
4849 * "\x01" // COM_QUIT command
4850 * };
4851 */
4852
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004853 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4854 * const char mysql41_client_auth_pkt[] = {
4855 * "\x0e\x00\x00\" // packet length
4856 * "\x01" // packet number
4857 * "\x00\x00\x00\x00" // client capabilities
4858 * "\x00\x00\x00\x01" // max packet
4859 * "\x21" // character set (UTF-8)
4860 * char[23] // All zeroes
4861 * "haproxy\x00" // username (null terminated string)
4862 * "\x00" // filler (always 0x00)
4863 * "\x01\x00\x00" // packet length
4864 * "\x00" // packet number
4865 * "\x01" // COM_QUIT command
4866 * };
4867 */
4868
4869
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004870 if (*(args[2])) {
4871 int cur_arg = 2;
4872
4873 while (*(args[cur_arg])) {
4874 if (strcmp(args[cur_arg], "user") == 0) {
4875 char *mysqluser;
4876 int packetlen, reqlen, userlen;
4877
4878 /* suboption header - needs additional argument for it */
4879 if (*(args[cur_arg+1]) == 0) {
4880 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4881 file, linenum, args[0], args[1], args[cur_arg]);
4882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
4884 }
4885 mysqluser = args[cur_arg + 1];
4886 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004887
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004888 if (*(args[cur_arg+2])) {
4889 if (!strcmp(args[cur_arg+2], "post-41")) {
4890 packetlen = userlen + 7 + 27;
4891 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004892
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004893 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004894 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004895 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004896
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004897 snprintf(curproxy->check_req, 4, "%c%c%c",
4898 ((unsigned char) packetlen & 0xff),
4899 ((unsigned char) (packetlen >> 8) & 0xff),
4900 ((unsigned char) (packetlen >> 16) & 0xff));
4901
4902 curproxy->check_req[3] = 1;
4903 curproxy->check_req[5] = 130;
4904 curproxy->check_req[11] = 1;
4905 curproxy->check_req[12] = 33;
4906 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4907 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4908 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4909 cur_arg += 3;
4910 } else {
4911 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
4914 }
4915 } else {
4916 packetlen = userlen + 7;
4917 reqlen = packetlen + 9;
4918
4919 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004920 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004921 curproxy->check_len = reqlen;
4922
4923 snprintf(curproxy->check_req, 4, "%c%c%c",
4924 ((unsigned char) packetlen & 0xff),
4925 ((unsigned char) (packetlen >> 8) & 0xff),
4926 ((unsigned char) (packetlen >> 16) & 0xff));
4927
4928 curproxy->check_req[3] = 1;
4929 curproxy->check_req[5] = 128;
4930 curproxy->check_req[8] = 1;
4931 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4932 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4933 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4934 cur_arg += 2;
4935 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004936 } else {
4937 /* unknown suboption - catchall */
4938 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4939 file, linenum, args[0], args[1]);
4940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942 }
4943 } /* end while loop */
4944 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004945 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004946 else if (!strcmp(args[1], "ldap-check")) {
4947 /* use LDAP request to check servers' health */
4948 free(curproxy->check_req);
4949 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004950 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004951 curproxy->options2 |= PR_O2_LDAP_CHK;
4952
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004953 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004954 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4955 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004956 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4957 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004958 }
Christopher Fauletba7bc162016-11-07 21:07:38 +01004959 else if (!strcmp(args[1], "spop-check")) {
4960 if (curproxy == &defproxy) {
4961 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n",
4962 file, linenum, args[0], args[1]);
4963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
4965 }
4966 if (curproxy->cap & PR_CAP_FE) {
4967 Alert("parsing [%s:%d] : '%s %s' not allowed in 'frontend' and 'listen' sections.\n",
4968 file, linenum, args[0], args[1]);
4969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
4971 }
4972
4973 /* use SPOE request to check servers' health */
4974 free(curproxy->check_req);
4975 curproxy->check_req = NULL;
4976 curproxy->options2 &= ~PR_O2_CHK_ANY;
4977 curproxy->options2 |= PR_O2_SPOP_CHK;
4978
Christopher Faulet8ef75252017-02-20 22:56:03 +01004979 if (spoe_prepare_healthcheck_request(&curproxy->check_req, &curproxy->check_len)) {
Christopher Fauletba7bc162016-11-07 21:07:38 +01004980 Alert("parsing [%s:%d] : failed to prepare SPOP healthcheck request.\n", file, linenum);
4981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
4983 }
4984 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4985 goto out;
4986 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004987 else if (!strcmp(args[1], "tcp-check")) {
4988 /* use raw TCPCHK send/expect to check servers' health */
4989 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4990 err_code |= ERR_WARN;
4991
4992 free(curproxy->check_req);
4993 curproxy->check_req = NULL;
4994 curproxy->options2 &= ~PR_O2_CHK_ANY;
4995 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004996 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4997 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004998 }
Simon Horman98637e52014-06-20 12:30:16 +09004999 else if (!strcmp(args[1], "external-check")) {
5000 /* excute an external command to check servers' health */
5001 free(curproxy->check_req);
5002 curproxy->check_req = NULL;
5003 curproxy->options2 &= ~PR_O2_CHK_ANY;
5004 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005005 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5006 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005007 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005008 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005009 int cur_arg;
5010
5011 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5012 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005013 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005014
Willy Tarreau87cf5142011-08-19 22:57:24 +02005015 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005016
5017 free(curproxy->fwdfor_hdr_name);
5018 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5019 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5020
5021 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5022 cur_arg = 2;
5023 while (*(args[cur_arg])) {
5024 if (!strcmp(args[cur_arg], "except")) {
5025 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005026 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005027 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5028 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005031 }
5032 /* flush useless bits */
5033 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005034 cur_arg += 2;
5035 } else if (!strcmp(args[cur_arg], "header")) {
5036 /* suboption header - needs additional argument for it */
5037 if (*(args[cur_arg+1]) == 0) {
5038 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5039 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005042 }
5043 free(curproxy->fwdfor_hdr_name);
5044 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5045 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5046 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005047 } else if (!strcmp(args[cur_arg], "if-none")) {
5048 curproxy->options &= ~PR_O_FF_ALWAYS;
5049 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005050 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005051 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005052 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005053 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005056 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005057 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005058 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005059 else if (!strcmp(args[1], "originalto")) {
5060 int cur_arg;
5061
5062 /* insert x-original-to field, but not for the IP address listed as an except.
5063 * set default options (ie: bitfield, header name, etc)
5064 */
5065
5066 curproxy->options |= PR_O_ORGTO;
5067
5068 free(curproxy->orgto_hdr_name);
5069 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5070 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5071
Willy Tarreau87cf5142011-08-19 22:57:24 +02005072 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005073 cur_arg = 2;
5074 while (*(args[cur_arg])) {
5075 if (!strcmp(args[cur_arg], "except")) {
5076 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005077 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 +02005078 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5079 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005082 }
5083 /* flush useless bits */
5084 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5085 cur_arg += 2;
5086 } else if (!strcmp(args[cur_arg], "header")) {
5087 /* suboption header - needs additional argument for it */
5088 if (*(args[cur_arg+1]) == 0) {
5089 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5090 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005093 }
5094 free(curproxy->orgto_hdr_name);
5095 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5096 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5097 cur_arg += 2;
5098 } else {
5099 /* unknown suboption - catchall */
5100 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5101 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005104 }
5105 } /* end while loop */
5106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 else {
5108 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
Willy Tarreau93893792009-07-23 13:19:11 +02005112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005114 else if (!strcmp(args[0], "default_backend")) {
5115 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005117
5118 if (*(args[1]) == 0) {
5119 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005122 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005123 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005124 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005125
5126 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5127 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005130 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005132
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005133 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5134 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 +01005135 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 /* enable reconnections to dispatch */
5138 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005139
5140 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005143 else if (!strcmp(args[0], "http-reuse")) {
5144 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5145 err_code |= ERR_WARN;
5146
5147 if (strcmp(args[1], "never") == 0) {
5148 /* enable a graceful server shutdown on an HTTP 404 response */
5149 curproxy->options &= ~PR_O_REUSE_MASK;
5150 curproxy->options |= PR_O_REUSE_NEVR;
5151 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5152 goto out;
5153 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005154 else if (strcmp(args[1], "safe") == 0) {
5155 /* enable a graceful server shutdown on an HTTP 404 response */
5156 curproxy->options &= ~PR_O_REUSE_MASK;
5157 curproxy->options |= PR_O_REUSE_SAFE;
5158 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5159 goto out;
5160 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005161 else if (strcmp(args[1], "aggressive") == 0) {
5162 curproxy->options &= ~PR_O_REUSE_MASK;
5163 curproxy->options |= PR_O_REUSE_AGGR;
5164 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5165 goto out;
5166 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005167 else if (strcmp(args[1], "always") == 0) {
5168 /* enable a graceful server shutdown on an HTTP 404 response */
5169 curproxy->options &= ~PR_O_REUSE_MASK;
5170 curproxy->options |= PR_O_REUSE_ALWS;
5171 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5172 goto out;
5173 }
5174 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005175 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
5178 }
5179 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005180 else if (!strcmp(args[0], "http-check")) {
5181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005183
5184 if (strcmp(args[1], "disable-on-404") == 0) {
5185 /* enable a graceful server shutdown on an HTTP 404 response */
5186 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005187 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5188 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005189 }
Willy Tarreauef781042010-01-27 11:53:01 +01005190 else if (strcmp(args[1], "send-state") == 0) {
5191 /* enable emission of the apparent state of a server in HTTP checks */
5192 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005193 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5194 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005195 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005196 else if (strcmp(args[1], "expect") == 0) {
5197 const char *ptr_arg;
5198 int cur_arg;
5199
5200 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5201 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205
5206 cur_arg = 2;
5207 /* consider exclamation marks, sole or at the beginning of a word */
5208 while (*(ptr_arg = args[cur_arg])) {
5209 while (*ptr_arg == '!') {
5210 curproxy->options2 ^= PR_O2_EXP_INV;
5211 ptr_arg++;
5212 }
5213 if (*ptr_arg)
5214 break;
5215 cur_arg++;
5216 }
5217 /* now ptr_arg points to the beginning of a word past any possible
5218 * exclamation mark, and cur_arg is the argument which holds this word.
5219 */
5220 if (strcmp(ptr_arg, "status") == 0) {
5221 if (!*(args[cur_arg + 1])) {
5222 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5223 file, linenum, args[0], args[1], ptr_arg);
5224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
5226 }
5227 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005228 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005229 curproxy->expect_str = strdup(args[cur_arg + 1]);
5230 }
5231 else if (strcmp(ptr_arg, "string") == 0) {
5232 if (!*(args[cur_arg + 1])) {
5233 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5234 file, linenum, args[0], args[1], ptr_arg);
5235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237 }
5238 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005239 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005240 curproxy->expect_str = strdup(args[cur_arg + 1]);
5241 }
5242 else if (strcmp(ptr_arg, "rstatus") == 0) {
5243 if (!*(args[cur_arg + 1])) {
5244 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5245 file, linenum, args[0], args[1], ptr_arg);
5246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005250 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005251 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005252 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005253 free(curproxy->expect_regex);
5254 curproxy->expect_regex = NULL;
5255 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005256 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005257 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5258 error = NULL;
5259 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5260 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5261 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5262 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
5266 }
5267 else if (strcmp(ptr_arg, "rstring") == 0) {
5268 if (!*(args[cur_arg + 1])) {
5269 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5270 file, linenum, args[0], args[1], ptr_arg);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005275 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005276 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005277 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005278 free(curproxy->expect_regex);
5279 curproxy->expect_regex = NULL;
5280 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005281 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005282 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5283 error = NULL;
5284 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5285 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5286 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5287 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005288 err_code |= ERR_ALERT | ERR_FATAL;
5289 goto out;
5290 }
5291 }
5292 else {
5293 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5294 file, linenum, args[0], args[1], ptr_arg);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005299 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005300 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 +02005301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005303 }
5304 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005305 else if (!strcmp(args[0], "tcp-check")) {
5306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5307 err_code |= ERR_WARN;
5308
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005309 if (strcmp(args[1], "comment") == 0) {
5310 int cur_arg;
5311 struct tcpcheck_rule *tcpcheck;
5312
5313 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005314 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005315 tcpcheck->action = TCPCHK_ACT_COMMENT;
5316
5317 if (!*args[cur_arg + 1]) {
5318 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5319 file, linenum, args[cur_arg]);
5320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
5322 }
5323
5324 tcpcheck->comment = strdup(args[cur_arg + 1]);
5325
5326 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005327 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5328 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005329 }
5330 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005331 const char *ptr_arg;
5332 int cur_arg;
5333 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005334
5335 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005336 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5337 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5338 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5339 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5340 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005341
Willy Tarreau5581c272015-05-13 12:24:53 +02005342 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5343 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5344 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5345 file, linenum);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005348 }
5349
5350 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005351 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005352 tcpcheck->action = TCPCHK_ACT_CONNECT;
5353
5354 /* parsing each parameters to fill up the rule */
5355 while (*(ptr_arg = args[cur_arg])) {
5356 /* tcp port */
5357 if (strcmp(args[cur_arg], "port") == 0) {
5358 if ( (atol(args[cur_arg + 1]) > 65535) ||
5359 (atol(args[cur_arg + 1]) < 1) ){
5360 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5361 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
5364 }
5365 tcpcheck->port = atol(args[cur_arg + 1]);
5366 cur_arg += 2;
5367 }
5368 /* send proxy protocol */
5369 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5370 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5371 cur_arg++;
5372 }
5373#ifdef USE_OPENSSL
5374 else if (strcmp(args[cur_arg], "ssl") == 0) {
5375 curproxy->options |= PR_O_TCPCHK_SSL;
5376 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5377 cur_arg++;
5378 }
5379#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005380 /* comment for this tcpcheck line */
5381 else if (strcmp(args[cur_arg], "comment") == 0) {
5382 if (!*args[cur_arg + 1]) {
5383 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5384 file, linenum, args[cur_arg]);
5385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387 }
5388 tcpcheck->comment = strdup(args[cur_arg + 1]);
5389 cur_arg += 2;
5390 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005391 else {
5392#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005393 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 +01005394#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005395 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 +01005396#endif /* USE_OPENSSL */
5397 file, linenum, args[0], args[1], args[cur_arg]);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
5401
5402 }
5403
5404 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5405 }
5406 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005407 if (! *(args[2]) ) {
5408 /* SEND string expected */
5409 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5410 file, linenum, args[0], args[1], args[2]);
5411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
5413 } else {
5414 struct tcpcheck_rule *tcpcheck;
5415
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005416 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005417
5418 tcpcheck->action = TCPCHK_ACT_SEND;
5419 tcpcheck->string_len = strlen(args[2]);
5420 tcpcheck->string = strdup(args[2]);
5421 tcpcheck->expect_regex = NULL;
5422
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005423 /* comment for this tcpcheck line */
5424 if (strcmp(args[3], "comment") == 0) {
5425 if (!*args[4]) {
5426 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5427 file, linenum, args[3]);
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
5431 tcpcheck->comment = strdup(args[4]);
5432 }
5433
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005434 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5435 }
5436 }
5437 else if (strcmp(args[1], "send-binary") == 0) {
5438 if (! *(args[2]) ) {
5439 /* SEND binary string expected */
5440 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5441 file, linenum, args[0], args[1], args[2]);
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 } else {
5445 struct tcpcheck_rule *tcpcheck;
5446 char *err = NULL;
5447
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005448 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005449
5450 tcpcheck->action = TCPCHK_ACT_SEND;
5451 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5452 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5453 file, linenum, args[0], args[1], args[2], err);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457 tcpcheck->expect_regex = NULL;
5458
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005459 /* comment for this tcpcheck line */
5460 if (strcmp(args[3], "comment") == 0) {
5461 if (!*args[4]) {
5462 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5463 file, linenum, args[3]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467 tcpcheck->comment = strdup(args[4]);
5468 }
5469
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005470 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5471 }
5472 }
5473 else if (strcmp(args[1], "expect") == 0) {
5474 const char *ptr_arg;
5475 int cur_arg;
5476 int inverse = 0;
5477
5478 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5479 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5480 err_code |= ERR_ALERT | ERR_FATAL;
5481 goto out;
5482 }
5483
5484 cur_arg = 2;
5485 /* consider exclamation marks, sole or at the beginning of a word */
5486 while (*(ptr_arg = args[cur_arg])) {
5487 while (*ptr_arg == '!') {
5488 inverse = !inverse;
5489 ptr_arg++;
5490 }
5491 if (*ptr_arg)
5492 break;
5493 cur_arg++;
5494 }
5495 /* now ptr_arg points to the beginning of a word past any possible
5496 * exclamation mark, and cur_arg is the argument which holds this word.
5497 */
5498 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005499 struct tcpcheck_rule *tcpcheck;
5500 char *err = NULL;
5501
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005502 if (!*(args[cur_arg + 1])) {
5503 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5504 file, linenum, args[0], args[1], ptr_arg);
5505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
5507 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005508
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005509 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005510
5511 tcpcheck->action = TCPCHK_ACT_EXPECT;
5512 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5513 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5514 file, linenum, args[0], args[1], args[2], err);
5515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
5517 }
5518 tcpcheck->expect_regex = NULL;
5519 tcpcheck->inverse = inverse;
5520
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005521 /* tcpcheck comment */
5522 cur_arg += 2;
5523 if (strcmp(args[cur_arg], "comment") == 0) {
5524 if (!*args[cur_arg + 1]) {
5525 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5526 file, linenum, args[cur_arg + 1]);
5527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
5530 tcpcheck->comment = strdup(args[cur_arg + 1]);
5531 }
5532
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005533 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5534 }
5535 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005536 struct tcpcheck_rule *tcpcheck;
5537
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005538 if (!*(args[cur_arg + 1])) {
5539 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5540 file, linenum, args[0], args[1], ptr_arg);
5541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005544
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005545 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005546
5547 tcpcheck->action = TCPCHK_ACT_EXPECT;
5548 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5549 tcpcheck->string = strdup(args[cur_arg + 1]);
5550 tcpcheck->expect_regex = NULL;
5551 tcpcheck->inverse = inverse;
5552
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005553 /* tcpcheck comment */
5554 cur_arg += 2;
5555 if (strcmp(args[cur_arg], "comment") == 0) {
5556 if (!*args[cur_arg + 1]) {
5557 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5558 file, linenum, args[cur_arg + 1]);
5559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
5561 }
5562 tcpcheck->comment = strdup(args[cur_arg + 1]);
5563 }
5564
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005565 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5566 }
5567 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005568 struct tcpcheck_rule *tcpcheck;
5569
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005570 if (!*(args[cur_arg + 1])) {
5571 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5572 file, linenum, args[0], args[1], ptr_arg);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005576
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005577 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005578
5579 tcpcheck->action = TCPCHK_ACT_EXPECT;
5580 tcpcheck->string_len = 0;
5581 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005582 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5583 error = NULL;
5584 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5585 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5586 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5587 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
5590 }
5591 tcpcheck->inverse = inverse;
5592
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005593 /* tcpcheck comment */
5594 cur_arg += 2;
5595 if (strcmp(args[cur_arg], "comment") == 0) {
5596 if (!*args[cur_arg + 1]) {
5597 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5598 file, linenum, args[cur_arg + 1]);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
5602 tcpcheck->comment = strdup(args[cur_arg + 1]);
5603 }
5604
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005605 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5606 }
5607 else {
5608 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5609 file, linenum, args[0], args[1], ptr_arg);
5610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
5612 }
5613 }
5614 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005615 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
5618 }
5619 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005620 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005621 if (curproxy == &defproxy) {
5622 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005625 }
5626
Willy Tarreaub80c2302007-11-30 20:51:32 +01005627 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005628 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005629
5630 if (strcmp(args[1], "fail") == 0) {
5631 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005632 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005633 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5634 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005637 }
5638
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005639 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5640 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5641 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005644 }
5645 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5646 }
5647 else {
5648 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005649 err_code |= ERR_ALERT | ERR_FATAL;
5650 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005651 }
5652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653#ifdef TPROXY
5654 else if (!strcmp(args[0], "transparent")) {
5655 /* enable transparent proxy connections */
5656 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005657 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 }
5660#endif
5661 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005664
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 if (*(args[1]) == 0) {
5666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005667 err_code |= ERR_ALERT | ERR_FATAL;
5668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005671 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005674 else if (!strcmp(args[0], "backlog")) { /* backlog */
5675 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005676 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005677
5678 if (*(args[1]) == 0) {
5679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005682 }
5683 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5685 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005686 }
Willy Tarreau86034312006-12-29 00:10:33 +01005687 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005688 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005690
Willy Tarreau86034312006-12-29 00:10:33 +01005691 if (*(args[1]) == 0) {
5692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005695 }
5696 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005697 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5698 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5701 if (*(args[1]) == 0) {
5702 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005706 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5707 if (err) {
5708 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5709 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005712 }
5713 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005714 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 }
5717 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005718 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005719 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005720 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005721
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722 if (curproxy == &defproxy) {
5723 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005727 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005728 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005729
Willy Tarreau48ef4c92017-01-06 18:32:38 +01005730 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005731 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005732 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005733 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005734 goto out;
5735 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005736
5737 proto = protocol_by_family(sk->ss_family);
5738 if (!proto || !proto->connect) {
5739 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5740 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
5743 }
5744
5745 if (port1 != port2) {
5746 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5747 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005751
5752 if (!port1) {
5753 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5754 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
5757 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005758
William Lallemanddf1425a2015-04-28 20:17:49 +02005759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5760 goto out;
5761
Willy Tarreaud5191e72010-02-09 20:50:45 +01005762 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005763 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
5765 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005768
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005769 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5770 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005775 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005776 /**
5777 * The syntax for hash-type config element is
5778 * hash-type {map-based|consistent} [[<algo>] avalanche]
5779 *
5780 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5781 */
5782 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005783
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5785 err_code |= ERR_WARN;
5786
5787 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005788 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5789 }
5790 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005791 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5792 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005793 else if (strcmp(args[1], "avalanche") == 0) {
5794 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]);
5795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005797 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005798 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005799 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
5802 }
Bhaskar98634f02013-10-29 23:30:51 -04005803
5804 /* set the hash function to use */
5805 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005806 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005807 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005808
5809 /* if consistent with no argument, then avalanche modifier is also applied */
5810 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5811 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005812 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005813 /* set the hash function */
5814 if (!strcmp(args[2], "sdbm")) {
5815 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5816 }
5817 else if (!strcmp(args[2], "djb2")) {
5818 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005819 }
5820 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005821 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005822 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005823 else if (!strcmp(args[2], "crc32")) {
5824 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5825 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005826 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005827 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 -05005828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
5830 }
5831
5832 /* set the hash modifier */
5833 if (!strcmp(args[3], "avalanche")) {
5834 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5835 }
5836 else if (*args[3]) {
5837 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5838 err_code |= ERR_ALERT | ERR_FATAL;
5839 goto out;
5840 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005841 }
William Lallemanda73203e2012-03-12 12:48:57 +01005842 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005843 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5844 if (*(args[1]) == 0) {
5845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
5848 }
5849 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5850 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5851 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5852 err_code |= ERR_ALERT | ERR_FATAL;
5853 goto out;
5854 }
5855 }
William Lallemanda73203e2012-03-12 12:48:57 +01005856 else if (strcmp(args[0], "unique-id-format") == 0) {
5857 if (!*(args[1])) {
5858 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5859 err_code |= ERR_ALERT | ERR_FATAL;
5860 goto out;
5861 }
William Lallemand3203ff42012-11-11 17:30:56 +01005862 if (*(args[2])) {
5863 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
5866 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005867 free(curproxy->conf.uniqueid_format_string);
5868 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005869
Willy Tarreau62a61232013-04-12 18:13:46 +02005870 free(curproxy->conf.uif_file);
5871 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5872 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005873 }
William Lallemanda73203e2012-03-12 12:48:57 +01005874
5875 else if (strcmp(args[0], "unique-id-header") == 0) {
5876 if (!*(args[1])) {
5877 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5878 err_code |= ERR_ALERT | ERR_FATAL;
5879 goto out;
5880 }
5881 free(curproxy->header_unique_id);
5882 curproxy->header_unique_id = strdup(args[1]);
5883 }
5884
William Lallemand723b73a2012-02-08 16:37:49 +01005885 else if (strcmp(args[0], "log-format") == 0) {
5886 if (!*(args[1])) {
5887 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5888 err_code |= ERR_ALERT | ERR_FATAL;
5889 goto out;
5890 }
William Lallemand3203ff42012-11-11 17:30:56 +01005891 if (*(args[2])) {
5892 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
5895 }
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005896 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
5897 char *oldlogformat = "log-format";
Willy Tarreau196729e2012-05-31 19:30:26 +02005898
Guillaume de Lafondea5b0e62017-03-31 19:54:09 +02005899 if (curproxy->conf.logformat_string == default_http_log_format)
5900 oldlogformat = "option httplog";
5901 else if (curproxy->conf.logformat_string == default_tcp_log_format)
5902 oldlogformat = "option tcplog";
5903 else if (curproxy->conf.logformat_string == clf_http_log_format)
5904 oldlogformat = "option httplog clf";
5905 Warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
5906 file, linenum, oldlogformat);
5907 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005908 if (curproxy->conf.logformat_string != default_http_log_format &&
5909 curproxy->conf.logformat_string != default_tcp_log_format &&
5910 curproxy->conf.logformat_string != clf_http_log_format)
5911 free(curproxy->conf.logformat_string);
5912 curproxy->conf.logformat_string = strdup(args[1]);
5913
5914 free(curproxy->conf.lfs_file);
5915 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5916 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005917
5918 /* get a chance to improve log-format error reporting by
5919 * reporting the correct line-number when possible.
5920 */
5921 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5922 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5923 file, linenum, curproxy->id);
5924 err_code |= ERR_WARN;
5925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005927 else if (!strcmp(args[0], "log-format-sd")) {
5928 if (!*(args[1])) {
5929 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
5933 if (*(args[2])) {
5934 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
5937 }
5938
5939 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5940 free(curproxy->conf.logformat_sd_string);
5941 curproxy->conf.logformat_sd_string = strdup(args[1]);
5942
5943 free(curproxy->conf.lfsd_file);
5944 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5945 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5946
5947 /* get a chance to improve log-format-sd error reporting by
5948 * reporting the correct line-number when possible.
5949 */
5950 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5951 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5952 file, linenum, curproxy->id);
5953 err_code |= ERR_WARN;
5954 }
5955 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005956 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5957 if (*(args[1]) == 0) {
5958 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5959 err_code |= ERR_ALERT | ERR_FATAL;
5960 goto out;
5961 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005962 chunk_destroy(&curproxy->log_tag);
5963 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005964 }
William Lallemand0f99e342011-10-12 17:50:54 +02005965 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5966 /* delete previous herited or defined syslog servers */
5967 struct logsrv *back;
5968
5969 if (*(args[1]) != 0) {
5970 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
5973 }
5974
William Lallemand723b73a2012-02-08 16:37:49 +01005975 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5976 LIST_DEL(&tmplogsrv->list);
5977 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005978 }
5979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005981 struct logsrv *logsrv;
5982
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005984 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005985 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02005986 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01005987 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005988 LIST_INIT(&node->list);
5989 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 }
5992 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005993 struct sockaddr_storage *sk;
5994 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005995 int arg = 0;
5996 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005997
Vincent Bernat02779b62016-04-03 13:48:43 +02005998 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005999
Willy Tarreau18324f52014-06-27 18:10:07 +02006000 /* just after the address, a length may be specified */
6001 if (strcmp(args[arg+2], "len") == 0) {
6002 len = atoi(args[arg+3]);
6003 if (len < 80 || len > 65535) {
6004 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6005 file, linenum, args[arg+3]);
6006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
6008 }
6009 logsrv->maxlen = len;
6010
6011 /* skip these two args */
6012 arg += 2;
6013 }
6014 else
6015 logsrv->maxlen = MAX_SYSLOG_LEN;
6016
6017 if (logsrv->maxlen > global.max_syslog_len) {
6018 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006019 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6020 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6021 logline = my_realloc2(logline, global.max_syslog_len + 1);
6022 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006023 }
6024
Dragan Dosen1322d092015-09-22 16:05:32 +02006025 /* after the length, a format may be specified */
6026 if (strcmp(args[arg+2], "format") == 0) {
6027 logsrv->format = get_log_format(args[arg+3]);
6028 if (logsrv->format < 0) {
6029 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6030 err_code |= ERR_ALERT | ERR_FATAL;
6031 goto out;
6032 }
6033
6034 /* skip these two args */
6035 arg += 2;
6036 }
6037
William Lallemanddf1425a2015-04-28 20:17:49 +02006038 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6039 goto out;
6040
Willy Tarreau18324f52014-06-27 18:10:07 +02006041 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006042 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006043 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006044 err_code |= ERR_ALERT | ERR_FATAL;
6045 goto out;
6046
Willy Tarreaubaaee002006-06-26 02:48:02 +02006047 }
6048
William Lallemand0f99e342011-10-12 17:50:54 +02006049 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006050 if (*(args[arg+3])) {
6051 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006052 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006053 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006054 err_code |= ERR_ALERT | ERR_FATAL;
6055 goto out;
6056
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057 }
6058 }
6059
William Lallemand0f99e342011-10-12 17:50:54 +02006060 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006061 if (*(args[arg+4])) {
6062 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006063 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006064 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
6067
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006068 }
6069 }
6070
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006071 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006072 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006073 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006075 goto out;
6076 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006077
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006078 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006079
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006080 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006081 if (port1 != port2) {
6082 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6083 file, linenum, args[0], args[1]);
6084 err_code |= ERR_ALERT | ERR_FATAL;
6085 goto out;
6086 }
6087
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006088 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006089 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006090 }
William Lallemand0f99e342011-10-12 17:50:54 +02006091
6092 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093 }
6094 else {
6095 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6096 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006097 err_code |= ERR_ALERT | ERR_FATAL;
6098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006099 }
6100 }
6101 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006102 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006103 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006104 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006105 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006106
Willy Tarreau977b8e42006-12-29 14:19:17 +01006107 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006108 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006109
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006111 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6112 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006113 err_code |= ERR_ALERT | ERR_FATAL;
6114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006115 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006116
6117 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006118 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6119 free(curproxy->conn_src.iface_name);
6120 curproxy->conn_src.iface_name = NULL;
6121 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006122
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006123 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006124 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006125 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006126 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006127 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006128 goto out;
6129 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006130
6131 proto = protocol_by_family(sk->ss_family);
6132 if (!proto || !proto->connect) {
6133 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006134 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006135 err_code |= ERR_ALERT | ERR_FATAL;
6136 goto out;
6137 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006138
6139 if (port1 != port2) {
6140 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6141 file, linenum, args[0], args[1]);
6142 err_code |= ERR_ALERT | ERR_FATAL;
6143 goto out;
6144 }
6145
Willy Tarreauef9a3602012-12-08 22:29:20 +01006146 curproxy->conn_src.source_addr = *sk;
6147 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006148
6149 cur_arg = 2;
6150 while (*(args[cur_arg])) {
6151 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006152#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006153 if (!*args[cur_arg + 1]) {
6154 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6155 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006156 err_code |= ERR_ALERT | ERR_FATAL;
6157 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006158 }
6159
6160 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006161 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6162 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006163 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006164 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6165 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006166 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6167 char *name, *end;
6168
6169 name = args[cur_arg+1] + 7;
6170 while (isspace(*name))
6171 name++;
6172
6173 end = name;
6174 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6175 end++;
6176
Willy Tarreauef9a3602012-12-08 22:29:20 +01006177 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6178 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6179 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6180 curproxy->conn_src.bind_hdr_len = end - name;
6181 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6182 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6183 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006184
6185 /* now look for an occurrence number */
6186 while (isspace(*end))
6187 end++;
6188 if (*end == ',') {
6189 end++;
6190 name = end;
6191 if (*end == '-')
6192 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006193 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006194 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006195 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006196 }
6197
Willy Tarreauef9a3602012-12-08 22:29:20 +01006198 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006199 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6200 " occurrences values smaller than %d.\n",
6201 file, linenum, MAX_HDR_HISTORY);
6202 err_code |= ERR_ALERT | ERR_FATAL;
6203 goto out;
6204 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006205 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006206 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006207
Willy Tarreau48ef4c92017-01-06 18:32:38 +01006208 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006209 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006210 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006211 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006212 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006213 goto out;
6214 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006215
6216 proto = protocol_by_family(sk->ss_family);
6217 if (!proto || !proto->connect) {
6218 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6219 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006220 err_code |= ERR_ALERT | ERR_FATAL;
6221 goto out;
6222 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006223
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006224 if (port1 != port2) {
6225 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6226 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006227 err_code |= ERR_ALERT | ERR_FATAL;
6228 goto out;
6229 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006230 curproxy->conn_src.tproxy_addr = *sk;
6231 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006232 }
6233 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006234#else /* no TPROXY support */
6235 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006236 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006237 err_code |= ERR_ALERT | ERR_FATAL;
6238 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006239#endif
6240 cur_arg += 2;
6241 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006242 }
6243
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006244 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6245#ifdef SO_BINDTODEVICE
6246 if (!*args[cur_arg + 1]) {
6247 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006249 err_code |= ERR_ALERT | ERR_FATAL;
6250 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006251 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006252 free(curproxy->conn_src.iface_name);
6253 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6254 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006255 global.last_checks |= LSTCHK_NETADM;
6256#else
6257 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6258 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006259 err_code |= ERR_ALERT | ERR_FATAL;
6260 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006261#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006262 cur_arg += 2;
6263 continue;
6264 }
6265 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006266 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006267 err_code |= ERR_ALERT | ERR_FATAL;
6268 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006270 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006271 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6272 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6273 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006274 err_code |= ERR_ALERT | ERR_FATAL;
6275 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006278 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6280 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006281 err_code |= ERR_ALERT | ERR_FATAL;
6282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006283 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006284
6285 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006286 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006287 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006288 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006290 }
6291 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006292 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006293 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006294 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006295 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297 }
6298 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006299 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006300 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006301 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006302 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006304 }
6305 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006306 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006307 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006308 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006309 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311 }
6312 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006313 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006314 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006315 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006316 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006319 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006320 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006321 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006322 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006323 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006324 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006327 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006330 err_code |= ERR_ALERT | ERR_FATAL;
6331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006332 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006333
6334 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006335 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006336 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006337 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 }
6340 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006341 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006342 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006343 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 }
6347 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006348 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006349 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006350 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006353 }
6354 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006356 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006357 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360 }
6361 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006363 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006364 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006368 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006370 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006371 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006373 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006376 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006377
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378 if (curproxy == &defproxy) {
6379 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006380 err_code |= ERR_ALERT | ERR_FATAL;
6381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006382 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006383 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006384 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 if (*(args[1]) == 0) {
6387 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006388 err_code |= ERR_ALERT | ERR_FATAL;
6389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006391
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006392 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006393 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6394 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6395 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006396 err_code |= ERR_ALERT | ERR_FATAL;
6397 goto out;
6398 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006399 err_code |= warnif_cond_conflicts(cond,
6400 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6401 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006402 }
6403 else if (*args[2]) {
6404 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6405 file, linenum, args[0], args[2]);
6406 err_code |= ERR_ALERT | ERR_FATAL;
6407 goto out;
6408 }
6409
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006410 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006411 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006412 wl->s = strdup(args[1]);
6413 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006414 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 }
6416 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006417 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006420 err_code |= ERR_ALERT | ERR_FATAL;
6421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006423
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006425 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006426 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006427 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 }
6430 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006432 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006433 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006434 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436 }
6437 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006439 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006440 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006441 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 }
6444 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006445 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6447 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 }
6451
Willy Tarreauade5ec42010-01-28 19:33:49 +01006452 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006453 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006454 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006455 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006457 }
6458 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006459 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006460 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006461 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006462 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006464 }
6465 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006466 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006467 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006468 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006469 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 }
6472 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006473 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006474
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 if (curproxy == &defproxy) {
6476 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006477 err_code |= ERR_ALERT | ERR_FATAL;
6478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006479 }
Christopher Faulet898566e2016-10-26 11:06:28 +02006480 else if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006481 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 if (*(args[1]) == 0) {
6484 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006485 err_code |= ERR_ALERT | ERR_FATAL;
6486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 }
6488
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006489 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006490 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6491 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6492 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006493 err_code |= ERR_ALERT | ERR_FATAL;
6494 goto out;
6495 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006496 err_code |= warnif_cond_conflicts(cond,
6497 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6498 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006499 }
6500 else if (*args[2]) {
6501 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6502 file, linenum, args[0], args[2]);
6503 err_code |= ERR_ALERT | ERR_FATAL;
6504 goto out;
6505 }
6506
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006507 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006508 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006509 wl->s = strdup(args[1]);
6510 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 }
6512 else if (!strcmp(args[0], "errorloc") ||
6513 !strcmp(args[0], "errorloc302") ||
6514 !strcmp(args[0], "errorloc303")) { /* error location */
6515 int errnum, errlen;
6516 char *err;
6517
Willy Tarreau977b8e42006-12-29 14:19:17 +01006518 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006519 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006520
Willy Tarreaubaaee002006-06-26 02:48:02 +02006521 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006522 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006523 err_code |= ERR_ALERT | ERR_FATAL;
6524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525 }
6526
6527 errnum = atol(args[1]);
6528 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006529 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6530 err = malloc(errlen);
6531 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006532 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006533 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6534 err = malloc(errlen);
6535 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006536 }
6537
Willy Tarreau0f772532006-12-23 20:51:41 +01006538 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6539 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006540 chunk_destroy(&curproxy->errmsg[rc]);
6541 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006542 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006545
6546 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006547 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6548 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 free(err);
6550 }
6551 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006552 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6553 int errnum, errlen, fd;
6554 char *err;
6555 struct stat stat;
6556
6557 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006558 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006559
6560 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006561 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006562 err_code |= ERR_ALERT | ERR_FATAL;
6563 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006564 }
6565
6566 fd = open(args[2], O_RDONLY);
6567 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6568 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6569 file, linenum, args[2], args[1]);
6570 if (fd >= 0)
6571 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006572 err_code |= ERR_ALERT | ERR_FATAL;
6573 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006574 }
6575
Willy Tarreau27a674e2009-08-17 07:23:33 +02006576 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006577 errlen = stat.st_size;
6578 } else {
6579 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006580 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006581 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006582 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006583 }
6584
6585 err = malloc(errlen); /* malloc() must succeed during parsing */
6586 errnum = read(fd, err, errlen);
6587 if (errnum != errlen) {
6588 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6589 file, linenum, args[2], args[1]);
6590 close(fd);
6591 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006592 err_code |= ERR_ALERT | ERR_FATAL;
6593 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006594 }
6595 close(fd);
6596
6597 errnum = atol(args[1]);
6598 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6599 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006600 chunk_destroy(&curproxy->errmsg[rc]);
6601 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006602 break;
6603 }
6604 }
6605
6606 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006607 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6608 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006609 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006610 free(err);
6611 }
6612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006614 struct cfg_kw_list *kwl;
6615 int index;
6616
6617 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6618 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6619 if (kwl->kw[index].section != CFG_LISTEN)
6620 continue;
6621 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6622 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006623 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006624 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006625 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006626 err_code |= ERR_ALERT | ERR_FATAL;
6627 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006628 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006629 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006630 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006631 err_code |= ERR_WARN;
6632 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006633 }
Willy Tarreau93893792009-07-23 13:19:11 +02006634 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006635 }
6636 }
6637 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006638
Willy Tarreau6daf3432008-01-22 16:44:08 +01006639 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006640 err_code |= ERR_ALERT | ERR_FATAL;
6641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006642 }
Willy Tarreau93893792009-07-23 13:19:11 +02006643 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006644 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006645 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006646}
6647
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006648int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006649cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6650{
6651#ifdef CONFIG_HAP_NS
6652 const char *err;
6653 const char *item = args[0];
6654
6655 if (!strcmp(item, "namespace_list")) {
6656 return 0;
6657 }
6658 else if (!strcmp(item, "namespace")) {
6659 size_t idx = 1;
6660 const char *current;
6661 while (*(current = args[idx++])) {
6662 err = invalid_char(current);
6663 if (err) {
6664 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6665 file, linenum, *err, item, current);
6666 return ERR_ALERT | ERR_FATAL;
6667 }
6668
6669 if (netns_store_lookup(current, strlen(current))) {
6670 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6671 file, linenum, current);
6672 return ERR_ALERT | ERR_FATAL;
6673 }
6674 if (!netns_store_insert(current)) {
6675 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6676 file, linenum, current);
6677 return ERR_ALERT | ERR_FATAL;
6678 }
6679 }
6680 }
6681
6682 return 0;
6683#else
6684 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6685 file, linenum);
6686 return ERR_ALERT | ERR_FATAL;
6687#endif
6688}
6689
6690int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006691cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6692{
6693
6694 int err_code = 0;
6695 const char *err;
6696
6697 if (!strcmp(args[0], "userlist")) { /* new userlist */
6698 struct userlist *newul;
6699
6700 if (!*args[1]) {
6701 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6702 file, linenum, args[0]);
6703 err_code |= ERR_ALERT | ERR_FATAL;
6704 goto out;
6705 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6707 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006708
6709 err = invalid_char(args[1]);
6710 if (err) {
6711 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6712 file, linenum, *err, args[0], args[1]);
6713 err_code |= ERR_ALERT | ERR_FATAL;
6714 goto out;
6715 }
6716
6717 for (newul = userlist; newul; newul = newul->next)
6718 if (!strcmp(newul->name, args[1])) {
6719 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6720 file, linenum, args[1]);
6721 err_code |= ERR_WARN;
6722 goto out;
6723 }
6724
Vincent Bernat02779b62016-04-03 13:48:43 +02006725 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006726 if (!newul) {
6727 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6728 err_code |= ERR_ALERT | ERR_ABORT;
6729 goto out;
6730 }
6731
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006733 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006734 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6735 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006736 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006737 goto out;
6738 }
6739
6740 newul->next = userlist;
6741 userlist = newul;
6742
6743 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006744 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006745 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006746 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006747
6748 if (!*args[1]) {
6749 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6750 file, linenum, args[0]);
6751 err_code |= ERR_ALERT | ERR_FATAL;
6752 goto out;
6753 }
6754
6755 err = invalid_char(args[1]);
6756 if (err) {
6757 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6758 file, linenum, *err, args[0], args[1]);
6759 err_code |= ERR_ALERT | ERR_FATAL;
6760 goto out;
6761 }
6762
William Lallemand4ac9f542015-05-28 18:03:51 +02006763 if (!userlist)
6764 goto out;
6765
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006766 for (ag = userlist->groups; ag; ag = ag->next)
6767 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006768 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6769 file, linenum, args[1], userlist->name);
6770 err_code |= ERR_ALERT;
6771 goto out;
6772 }
6773
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006774 ag = calloc(1, sizeof(*ag));
6775 if (!ag) {
6776 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6777 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006778 goto out;
6779 }
6780
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006781 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006782 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006783 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6784 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006785 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006786 goto out;
6787 }
6788
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006789 cur_arg = 2;
6790
6791 while (*args[cur_arg]) {
6792 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006793 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006794 cur_arg += 2;
6795 continue;
6796 } else {
6797 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6798 file, linenum, args[0]);
6799 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006800 free(ag->groupusers);
6801 free(ag->name);
6802 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803 goto out;
6804 }
6805 }
6806
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006807 ag->next = userlist->groups;
6808 userlist->groups = ag;
6809
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006810 } else if (!strcmp(args[0], "user")) { /* new user */
6811 struct auth_users *newuser;
6812 int cur_arg;
6813
6814 if (!*args[1]) {
6815 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6816 file, linenum, args[0]);
6817 err_code |= ERR_ALERT | ERR_FATAL;
6818 goto out;
6819 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006820 if (!userlist)
6821 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006822
6823 for (newuser = userlist->users; newuser; newuser = newuser->next)
6824 if (!strcmp(newuser->user, args[1])) {
6825 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6826 file, linenum, args[1], userlist->name);
6827 err_code |= ERR_ALERT;
6828 goto out;
6829 }
6830
Vincent Bernat02779b62016-04-03 13:48:43 +02006831 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006832 if (!newuser) {
6833 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6834 err_code |= ERR_ALERT | ERR_ABORT;
6835 goto out;
6836 }
6837
6838 newuser->user = strdup(args[1]);
6839
6840 newuser->next = userlist->users;
6841 userlist->users = newuser;
6842
6843 cur_arg = 2;
6844
6845 while (*args[cur_arg]) {
6846 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006847#ifdef CONFIG_HAP_CRYPT
6848 if (!crypt("", args[cur_arg + 1])) {
6849 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6850 file, linenum, newuser->user);
6851 err_code |= ERR_ALERT | ERR_FATAL;
6852 goto out;
6853 }
6854#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006855 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6856 file, linenum);
6857 err_code |= ERR_ALERT;
6858#endif
6859 newuser->pass = strdup(args[cur_arg + 1]);
6860 cur_arg += 2;
6861 continue;
6862 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6863 newuser->pass = strdup(args[cur_arg + 1]);
6864 newuser->flags |= AU_O_INSECURE;
6865 cur_arg += 2;
6866 continue;
6867 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006868 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006869 cur_arg += 2;
6870 continue;
6871 } else {
6872 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6873 file, linenum, args[0]);
6874 err_code |= ERR_ALERT | ERR_FATAL;
6875 goto out;
6876 }
6877 }
6878 } else {
6879 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6880 err_code |= ERR_ALERT | ERR_FATAL;
6881 }
6882
6883out:
6884 return err_code;
6885}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006886
Christopher Faulet79bdef32016-11-04 22:36:15 +01006887int
6888cfg_parse_scope(const char *file, int linenum, char *line)
6889{
6890 char *beg, *end, *scope = NULL;
6891 int err_code = 0;
6892 const char *err;
6893
6894 beg = line + 1;
6895 end = strchr(beg, ']');
6896
6897 /* Detect end of scope declaration */
6898 if (!end || end == beg) {
6899 Alert("parsing [%s:%d] : empty scope name is forbidden.\n",
6900 file, linenum);
6901 err_code |= ERR_ALERT | ERR_FATAL;
6902 goto out;
6903 }
6904
6905 /* Get scope name and check its validity */
6906 scope = my_strndup(beg, end-beg);
6907 err = invalid_char(scope);
6908 if (err) {
6909 Alert("parsing [%s:%d] : character '%c' is not permitted in a scope name.\n",
6910 file, linenum, *err);
6911 err_code |= ERR_ALERT | ERR_ABORT;
6912 goto out;
6913 }
6914
6915 /* Be sure to have a scope declaration alone on its line */
6916 line = end+1;
6917 while (isspace((unsigned char)*line))
6918 line++;
6919 if (*line && *line != '#' && *line != '\n' && *line != '\r') {
6920 Alert("parsing [%s:%d] : character '%c' is not permitted after scope declaration.\n",
6921 file, linenum, *line);
6922 err_code |= ERR_ALERT | ERR_ABORT;
6923 goto out;
6924 }
6925
6926 /* We have a valid scope declaration, save it */
6927 free(cfg_scope);
6928 cfg_scope = scope;
6929 scope = NULL;
6930
6931 out:
6932 free(scope);
6933 return err_code;
6934}
6935
Willy Tarreaubaaee002006-06-26 02:48:02 +02006936/*
6937 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006938 * Returns the error code, 0 if OK, or any combination of :
6939 * - ERR_ABORT: must abort ASAP
6940 * - ERR_FATAL: we can continue parsing but not start the service
6941 * - ERR_WARN: a warning has been emitted
6942 * - ERR_ALERT: an alert has been emitted
6943 * Only the two first ones can stop processing, the two others are just
6944 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006945 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006946int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006947{
William Lallemand64e84512015-05-12 14:25:37 +02006948 char *thisline;
6949 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950 FILE *f;
6951 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006952 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006953 struct cfg_section *cs = NULL;
6954 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006955 int readbytes = 0;
6956
6957 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006958 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006959 return -1;
6960 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006961
David Carlier97880bb2016-04-08 10:35:26 +01006962 if ((f=fopen(file,"r")) == NULL) {
6963 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006964 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006966
William Lallemandb2f07452015-05-12 14:27:13 +02006967next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006968 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006969 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006970 char *end;
6971 char *args[MAX_LINE_ARGS + 1];
6972 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006973 int dquote = 0; /* double quote */
6974 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006975
Willy Tarreaubaaee002006-06-26 02:48:02 +02006976 linenum++;
6977
6978 end = line + strlen(line);
6979
William Lallemand64e84512015-05-12 14:25:37 +02006980 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006981 /* Check if we reached the limit and the last char is not \n.
6982 * Watch out for the last line without the terminating '\n'!
6983 */
William Lallemand64e84512015-05-12 14:25:37 +02006984 char *newline;
6985 int newlinesize = linesize * 2;
6986
6987 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6988 if (newline == NULL) {
6989 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6990 file, linenum);
6991 err_code |= ERR_ALERT | ERR_FATAL;
6992 continue;
6993 }
6994
6995 readbytes = linesize - 1;
6996 linesize = newlinesize;
6997 thisline = newline;
6998 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006999 }
7000
William Lallemand64e84512015-05-12 14:25:37 +02007001 readbytes = 0;
7002
Willy Tarreaubaaee002006-06-26 02:48:02 +02007003 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007004 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007006
Christopher Faulet79bdef32016-11-04 22:36:15 +01007007
7008 if (*line == '[') {/* This is the begining if a scope */
7009 err_code |= cfg_parse_scope(file, linenum, line);
7010 goto next_line;
7011 }
7012
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013 arg = 0;
7014 args[arg] = line;
7015
7016 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007017 if (*line == '"' && !squote) { /* double quote outside single quotes */
7018 if (dquote)
7019 dquote = 0;
7020 else
7021 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007022 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007023 end--;
7024 }
7025 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7026 if (squote)
7027 squote = 0;
7028 else
7029 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007030 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007031 end--;
7032 }
7033 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7035 * C equivalent value. Other combinations left unchanged (eg: \1).
7036 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037 int skip = 0;
7038 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7039 *line = line[1];
7040 skip = 1;
7041 }
7042 else if (line[1] == 'r') {
7043 *line = '\r';
7044 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007046 else if (line[1] == 'n') {
7047 *line = '\n';
7048 skip = 1;
7049 }
7050 else if (line[1] == 't') {
7051 *line = '\t';
7052 skip = 1;
7053 }
7054 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007055 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007056 unsigned char hex1, hex2;
7057 hex1 = toupper(line[2]) - '0';
7058 hex2 = toupper(line[3]) - '0';
7059 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7060 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7061 *line = (hex1<<4) + hex2;
7062 skip = 3;
7063 }
7064 else {
7065 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007066 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007067 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007068 } else if (line[1] == '"') {
7069 *line = '"';
7070 skip = 1;
7071 } else if (line[1] == '\'') {
7072 *line = '\'';
7073 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007074 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7075 *line = '$';
7076 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007077 }
7078 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007079 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 end -= skip;
7081 }
7082 line++;
7083 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007084 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007085 /* end of string, end of loop */
7086 *line = 0;
7087 break;
7088 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007089 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007090 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007091 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007092 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 line++;
7094 args[++arg] = line;
7095 }
William Lallemandb2f07452015-05-12 14:27:13 +02007096 else if (dquote && *line == '$') {
7097 /* environment variables are evaluated inside double quotes */
7098 char *var_beg;
7099 char *var_end;
7100 char save_char;
7101 char *value;
7102 int val_len;
7103 int newlinesize;
7104 int braces = 0;
7105
7106 var_beg = line + 1;
7107 var_end = var_beg;
7108
7109 if (*var_beg == '{') {
7110 var_beg++;
7111 var_end++;
7112 braces = 1;
7113 }
7114
7115 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7116 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7117 err_code |= ERR_ALERT | ERR_FATAL;
7118 goto next_line; /* skip current line */
7119 }
7120
7121 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7122 var_end++;
7123
7124 save_char = *var_end;
7125 *var_end = '\0';
7126 value = getenv(var_beg);
7127 *var_end = save_char;
7128 val_len = value ? strlen(value) : 0;
7129
7130 if (braces) {
7131 if (*var_end == '}') {
7132 var_end++;
7133 braces = 0;
7134 } else {
7135 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7136 err_code |= ERR_ALERT | ERR_FATAL;
7137 goto next_line; /* skip current line */
7138 }
7139 }
7140
7141 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7142
7143 /* if not enough space in thisline */
7144 if (newlinesize > linesize) {
7145 char *newline;
7146
7147 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7148 if (newline == NULL) {
7149 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7150 err_code |= ERR_ALERT | ERR_FATAL;
7151 goto next_line; /* slip current line */
7152 }
7153 /* recompute pointers if realloc returns a new pointer */
7154 if (newline != thisline) {
7155 int i;
7156 int diff;
7157
7158 for (i = 0; i <= arg; i++) {
7159 diff = args[i] - thisline;
7160 args[i] = newline + diff;
7161 }
7162
7163 diff = var_end - thisline;
7164 var_end = newline + diff;
7165 diff = end - thisline;
7166 end = newline + diff;
7167 diff = line - thisline;
7168 line = newline + diff;
7169 thisline = newline;
7170 }
7171 linesize = newlinesize;
7172 }
7173
7174 /* insert value inside the line */
7175 memmove(line + val_len, var_end, end - var_end + 1);
7176 memcpy(line, value, val_len);
7177 end += val_len - (var_end - line);
7178 line += val_len;
7179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007180 else {
7181 line++;
7182 }
7183 }
William Lallemandb2f07452015-05-12 14:27:13 +02007184
William Lallemandf9873ba2015-05-05 17:37:14 +02007185 if (dquote) {
7186 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7187 err_code |= ERR_ALERT | ERR_FATAL;
7188 }
7189
7190 if (squote) {
7191 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7192 err_code |= ERR_ALERT | ERR_FATAL;
7193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007194
7195 /* empty line */
7196 if (!**args)
7197 continue;
7198
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007199 if (*line) {
7200 /* we had to stop due to too many args.
7201 * Let's terminate the string, print the offending part then cut the
7202 * last arg.
7203 */
7204 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7205 line++;
7206 *line = '\0';
7207
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007208 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007209 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007210 err_code |= ERR_ALERT | ERR_FATAL;
7211 args[arg] = line;
7212 }
7213
Willy Tarreau540abe42007-05-02 20:50:16 +02007214 /* zero out remaining args and ensure that at least one entry
7215 * is zeroed out.
7216 */
7217 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007218 args[arg] = line;
7219 }
7220
Willy Tarreau3842f002009-06-14 11:39:52 +02007221 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007222 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007223 char *tmp;
7224
Willy Tarreau3842f002009-06-14 11:39:52 +02007225 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007226 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007227 for (arg=0; *args[arg+1]; arg++)
7228 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007229 *tmp = '\0'; // fix the next arg to \0
7230 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007231 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007232 else if (!strcmp(args[0], "default")) {
7233 kwm = KWM_DEF;
7234 for (arg=0; *args[arg+1]; arg++)
7235 args[arg] = args[arg+1]; // shift args after inversion
7236 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007237
William Lallemand0f99e342011-10-12 17:50:54 +02007238 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7239 strcmp(args[0], "log") != 0) {
7240 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007241 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007242 }
7243
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007244 /* detect section start */
7245 list_for_each_entry(ics, &sections, list) {
7246 if (strcmp(args[0], ics->section_name) == 0) {
7247 cursection = ics->section_name;
7248 cs = ics;
7249 break;
7250 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007251 }
7252
Willy Tarreaubaaee002006-06-26 02:48:02 +02007253 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007254 if (cs)
7255 err_code |= cs->section_parser(file, linenum, args, kwm);
7256 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007257 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007258 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007259 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007260
7261 if (err_code & ERR_ABORT)
7262 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007263 }
Christopher Faulet79bdef32016-11-04 22:36:15 +01007264 free(cfg_scope);
7265 cfg_scope = NULL;
Willy Tarreau6daf3432008-01-22 16:44:08 +01007266 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007267 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007268 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007269 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007270}
7271
Willy Tarreau64ab6072014-09-16 12:17:36 +02007272/* This function propagates processes from frontend <from> to backend <to> so
7273 * that it is always guaranteed that a backend pointed to by a frontend is
7274 * bound to all of its processes. After that, if the target is a "listen"
7275 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007276 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007277 * checked first to ensure that <to> is already bound to all processes of
7278 * <from>, there is no risk of looping and we ensure to follow the shortest
7279 * path to the destination.
7280 *
7281 * It is possible to set <to> to NULL for the first call so that the function
7282 * takes care of visiting the initial frontend in <from>.
7283 *
7284 * It is important to note that the function relies on the fact that all names
7285 * have already been resolved.
7286 */
7287void propagate_processes(struct proxy *from, struct proxy *to)
7288{
7289 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007290
7291 if (to) {
7292 /* check whether we need to go down */
7293 if (from->bind_proc &&
7294 (from->bind_proc & to->bind_proc) == from->bind_proc)
7295 return;
7296
7297 if (!from->bind_proc && !to->bind_proc)
7298 return;
7299
7300 to->bind_proc = from->bind_proc ?
7301 (to->bind_proc | from->bind_proc) : 0;
7302
7303 /* now propagate down */
7304 from = to;
7305 }
7306
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007307 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007308 return;
7309
Willy Tarreauf6b70012014-12-18 14:00:43 +01007310 if (from->state == PR_STSTOPPED)
7311 return;
7312
Willy Tarreau64ab6072014-09-16 12:17:36 +02007313 /* default_backend */
7314 if (from->defbe.be)
7315 propagate_processes(from, from->defbe.be);
7316
7317 /* use_backend */
7318 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007319 if (rule->dynamic)
7320 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007321 to = rule->be.backend;
7322 propagate_processes(from, to);
7323 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324}
7325
Willy Tarreaubb925012009-07-23 13:36:36 +02007326/*
7327 * Returns the error code, 0 if OK, or any combination of :
7328 * - ERR_ABORT: must abort ASAP
7329 * - ERR_FATAL: we can continue parsing but not start the service
7330 * - ERR_WARN: a warning has been emitted
7331 * - ERR_ALERT: an alert has been emitted
7332 * Only the two first ones can stop processing, the two others are just
7333 * indicators.
7334 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007335int check_config_validity()
7336{
7337 int cfgerr = 0;
7338 struct proxy *curproxy = NULL;
7339 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007340 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007341 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007342 struct bind_conf *bind_conf;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007343 char *err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007344
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007345 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007346 /*
7347 * Now, check for the integrity of all that we have collected.
7348 */
7349
7350 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007351 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007352
Willy Tarreau193b8c62012-11-22 00:17:38 +01007353 if (!global.tune.max_http_hdr)
7354 global.tune.max_http_hdr = MAX_HTTP_HDR;
7355
7356 if (!global.tune.cookie_len)
7357 global.tune.cookie_len = CAPTURE_LEN;
7358
7359 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7360
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007361 /* Post initialisation of the users and groups lists. */
7362 err_code = userlist_postinit();
7363 if (err_code != ERR_NONE)
7364 goto out;
7365
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007366 /* first, we will invert the proxy list order */
7367 curproxy = NULL;
7368 while (proxy) {
7369 struct proxy *next;
7370
7371 next = proxy->next;
7372 proxy->next = curproxy;
7373 curproxy = proxy;
7374 if (!next)
7375 break;
7376 proxy = next;
7377 }
7378
Willy Tarreau419ead82014-09-16 13:41:21 +02007379 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007380 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007381 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007382 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007383 struct act_rule *trule;
7384 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007385 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007386 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007387 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007388
Willy Tarreau050536d2012-10-04 08:47:34 +02007389 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007390 /* proxy ID not set, use automatic numbering with first
7391 * spare entry starting with next_pxid.
7392 */
7393 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7394 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7395 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007396 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007397 next_pxid++;
7398
Willy Tarreau55ea7572007-06-17 19:56:27 +02007399
Willy Tarreaubaaee002006-06-26 02:48:02 +02007400 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007401 /* ensure we don't keep listeners uselessly bound */
7402 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007403 free((void *)curproxy->table.peers.name);
7404 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007405 continue;
7406 }
7407
Willy Tarreau102df612014-05-07 23:56:38 +02007408 /* Check multi-process mode compatibility for the current proxy */
7409
7410 if (curproxy->bind_proc) {
7411 /* an explicit bind-process was specified, let's check how many
7412 * processes remain.
7413 */
David Carliere6c39412015-07-02 07:00:17 +00007414 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007415
7416 curproxy->bind_proc &= nbits(global.nbproc);
7417 if (!curproxy->bind_proc && nbproc == 1) {
7418 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);
7419 curproxy->bind_proc = 1;
7420 }
7421 else if (!curproxy->bind_proc && nbproc > 1) {
7422 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);
7423 curproxy->bind_proc = 0;
7424 }
7425 }
7426
Willy Tarreau3d209582014-05-09 17:06:11 +02007427 /* check and reduce the bind-proc of each listener */
7428 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7429 unsigned long mask;
7430
7431 if (!bind_conf->bind_proc)
7432 continue;
7433
7434 mask = nbits(global.nbproc);
7435 if (curproxy->bind_proc)
7436 mask &= curproxy->bind_proc;
7437 /* mask cannot be null here thanks to the previous checks */
7438
David Carliere6c39412015-07-02 07:00:17 +00007439 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007440 bind_conf->bind_proc &= mask;
7441
7442 if (!bind_conf->bind_proc && nbproc == 1) {
7443 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",
7444 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7445 bind_conf->bind_proc = mask & ~(mask - 1);
7446 }
7447 else if (!bind_conf->bind_proc && nbproc > 1) {
7448 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",
7449 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7450 bind_conf->bind_proc = 0;
7451 }
7452 }
7453
Willy Tarreauff01a212009-03-15 13:46:16 +01007454 switch (curproxy->mode) {
7455 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007456 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007457 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007458 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7459 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007460 cfgerr++;
7461 }
7462
7463 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007464 Warning("config : servers will be ignored for %s '%s'.\n",
7465 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007466 break;
7467
7468 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007469 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007470 break;
7471
7472 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007473 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007474 break;
7475 }
7476
Willy Tarreauf3934b82015-08-11 11:36:45 +02007477 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7478 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7479 proxy_type_str(curproxy), curproxy->id);
7480 err_code |= ERR_WARN;
7481 }
7482
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007483 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007484 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007485 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007486 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7487 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007488 cfgerr++;
7489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007490#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007491 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007492 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7493 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007494 cfgerr++;
7495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007496#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007497 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007498 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7499 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007500 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007501 }
7502 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007503 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007504 /* If no LB algo is set in a backend, and we're not in
7505 * transparent mode, dispatch mode nor proxy mode, we
7506 * want to use balance roundrobin by default.
7507 */
7508 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7509 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007510 }
7511 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007512
Willy Tarreau1620ec32011-08-06 17:05:02 +02007513 if (curproxy->options & PR_O_DISPATCH)
7514 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7515 else if (curproxy->options & PR_O_HTTP_PROXY)
7516 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7517 else if (curproxy->options & PR_O_TRANSP)
7518 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007519
Willy Tarreau1620ec32011-08-06 17:05:02 +02007520 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7521 if (curproxy->options & PR_O_DISABLE404) {
7522 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7523 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7524 err_code |= ERR_WARN;
7525 curproxy->options &= ~PR_O_DISABLE404;
7526 }
7527 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7528 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7529 "send-state", proxy_type_str(curproxy), curproxy->id);
7530 err_code |= ERR_WARN;
7531 curproxy->options &= ~PR_O2_CHK_SNDST;
7532 }
Willy Tarreauef781042010-01-27 11:53:01 +01007533 }
7534
Simon Horman98637e52014-06-20 12:30:16 +09007535 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7536 if (!global.external_check) {
7537 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7538 curproxy->id, "option external-check");
7539 cfgerr++;
7540 }
7541 if (!curproxy->check_command) {
7542 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7543 curproxy->id, "option external-check");
7544 cfgerr++;
7545 }
7546 }
7547
Simon Horman64e34162015-02-06 11:11:57 +09007548 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007549 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7550 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007551 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7552 "'email-alert myhostname', or 'email-alert to' "
7553 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007554 "to be present).\n",
7555 proxy_type_str(curproxy), curproxy->id);
7556 err_code |= ERR_WARN;
7557 free_email_alert(curproxy);
7558 }
7559 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007560 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007561 }
7562
Simon Horman98637e52014-06-20 12:30:16 +09007563 if (curproxy->check_command) {
7564 int clear = 0;
7565 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7566 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7567 "external-check command", proxy_type_str(curproxy), curproxy->id);
7568 err_code |= ERR_WARN;
7569 clear = 1;
7570 }
7571 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007572 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007573 curproxy->id, "external-check command");
7574 cfgerr++;
7575 }
7576 if (clear) {
7577 free(curproxy->check_command);
7578 curproxy->check_command = NULL;
7579 }
7580 }
7581
7582 if (curproxy->check_path) {
7583 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7584 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7585 "external-check path", proxy_type_str(curproxy), curproxy->id);
7586 err_code |= ERR_WARN;
7587 free(curproxy->check_path);
7588 curproxy->check_path = NULL;
7589 }
7590 }
7591
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007592 /* if a default backend was specified, let's find it */
7593 if (curproxy->defbe.name) {
7594 struct proxy *target;
7595
Willy Tarreauafb39922015-05-26 12:04:09 +02007596 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007597 if (!target) {
7598 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7599 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007600 cfgerr++;
7601 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007602 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7603 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007604 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007605 } else if (target->mode != curproxy->mode &&
7606 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7607
7608 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7609 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7610 curproxy->conf.file, curproxy->conf.line,
7611 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7612 target->conf.file, target->conf.line);
7613 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007614 } else {
7615 free(curproxy->defbe.name);
7616 curproxy->defbe.be = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007617 /* Update tot_fe_maxconn for a further fullconn's computation */
7618 target->tot_fe_maxconn += curproxy->maxconn;
Willy Tarreauff678132012-02-13 14:32:34 +01007619 /* Emit a warning if this proxy also has some servers */
7620 if (curproxy->srv) {
7621 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7622 curproxy->id);
7623 err_code |= ERR_WARN;
7624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007625 }
7626 }
7627
Emeric Brun3f783572017-01-12 11:21:28 +01007628 if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
7629 /* Case of listen without default backend
7630 * The curproxy will be its own default backend
7631 * so we update tot_fe_maxconn for a further
7632 * fullconn's computation */
7633 curproxy->tot_fe_maxconn += curproxy->maxconn;
7634 }
7635
Willy Tarreau55ea7572007-06-17 19:56:27 +02007636 /* find the target proxy for 'use_backend' rules */
7637 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007638 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007639 struct logformat_node *node;
7640 char *pxname;
7641
7642 /* Try to parse the string as a log format expression. If the result
7643 * of the parsing is only one entry containing a simple string, then
7644 * it's a standard string corresponding to a static rule, thus the
7645 * parsing is cancelled and be.name is restored to be resolved.
7646 */
7647 pxname = rule->be.name;
7648 LIST_INIT(&rule->be.expr);
Thierry FOURNIER / OZON.IO4ed1c952016-11-24 23:57:54 +01007649 curproxy->conf.args.ctx = ARGC_UBK;
7650 curproxy->conf.args.file = rule->file;
7651 curproxy->conf.args.line = rule->line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01007652 err = NULL;
7653 if (!parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR, &err)) {
7654 Alert("Parsing [%s:%d]: failed to parse use_backend rule '%s' : %s.\n",
7655 rule->file, rule->line, pxname, err);
7656 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01007657 cfgerr++;
7658 continue;
7659 }
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007660 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7661
7662 if (!LIST_ISEMPTY(&rule->be.expr)) {
7663 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7664 rule->dynamic = 1;
7665 free(pxname);
7666 continue;
7667 }
7668 /* simple string: free the expression and fall back to static rule */
7669 free(node->arg);
7670 free(node);
7671 }
7672
7673 rule->dynamic = 0;
7674 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007675
Willy Tarreauafb39922015-05-26 12:04:09 +02007676 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007677 if (!target) {
7678 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7679 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007680 cfgerr++;
7681 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007682 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7683 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007684 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007685 } else if (target->mode != curproxy->mode &&
7686 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7687
7688 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7689 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7690 curproxy->conf.file, curproxy->conf.line,
7691 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7692 target->conf.file, target->conf.line);
7693 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007694 } else {
7695 free((void *)rule->be.name);
7696 rule->be.backend = target;
Emeric Brun3f783572017-01-12 11:21:28 +01007697 /* For each target of switching rules, we update
7698 * their tot_fe_maxconn, except if a previous rule point
7699 * on the same backend or on the default backend */
7700 if (rule->be.backend != curproxy->defbe.be) {
7701 struct switching_rule *swrule;
7702
7703 list_for_each_entry(swrule, &curproxy->switching_rules, list) {
7704 if (rule == swrule) {
7705 target->tot_fe_maxconn += curproxy->maxconn;
7706 break;
7707 }
7708 else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
7709 /* there is multiple ref of this backend */
7710 break;
7711 }
7712 }
7713 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007714 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007715 }
7716
Willy Tarreau64ab6072014-09-16 12:17:36 +02007717 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007718 list_for_each_entry(srule, &curproxy->server_rules, list) {
7719 struct server *target = findserver(curproxy, srule->srv.name);
7720
7721 if (!target) {
7722 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7723 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7724 cfgerr++;
7725 continue;
7726 }
7727 free((void *)srule->srv.name);
7728 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007729 }
7730
Emeric Brunb982a3d2010-01-04 15:45:53 +01007731 /* find the target table for 'stick' rules */
7732 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7733 struct proxy *target;
7734
Emeric Brun1d33b292010-01-04 15:47:17 +01007735 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7736 if (mrule->flags & STK_IS_STORE)
7737 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7738
Emeric Brunb982a3d2010-01-04 15:45:53 +01007739 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007740 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007741 else
7742 target = curproxy;
7743
7744 if (!target) {
7745 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7746 curproxy->id, mrule->table.name);
7747 cfgerr++;
7748 }
7749 else if (target->table.size == 0) {
7750 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7751 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7752 cfgerr++;
7753 }
Willy Tarreau12785782012-04-27 21:37:17 +02007754 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7755 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007756 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7757 cfgerr++;
7758 }
7759 else {
7760 free((void *)mrule->table.name);
7761 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007762 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007763 }
7764 }
7765
7766 /* find the target table for 'store response' rules */
7767 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7768 struct proxy *target;
7769
Emeric Brun1d33b292010-01-04 15:47:17 +01007770 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7771
Emeric Brunb982a3d2010-01-04 15:45:53 +01007772 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007773 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007774 else
7775 target = curproxy;
7776
7777 if (!target) {
7778 Alert("Proxy '%s': unable to find store table '%s'.\n",
7779 curproxy->id, mrule->table.name);
7780 cfgerr++;
7781 }
7782 else if (target->table.size == 0) {
7783 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7784 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7785 cfgerr++;
7786 }
Willy Tarreau12785782012-04-27 21:37:17 +02007787 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7788 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007789 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7790 cfgerr++;
7791 }
7792 else {
7793 free((void *)mrule->table.name);
7794 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007795 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007796 }
7797 }
7798
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007799 /* find the target table for 'tcp-request' layer 4 rules */
7800 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7801 struct proxy *target;
7802
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007803 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007804 continue;
7805
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007806 if (trule->arg.trk_ctr.table.n)
7807 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007808 else
7809 target = curproxy;
7810
7811 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007812 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007813 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007814 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007815 cfgerr++;
7816 }
7817 else if (target->table.size == 0) {
7818 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007819 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007820 cfgerr++;
7821 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007822 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007823 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007824 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007825 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007826 cfgerr++;
7827 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007828 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007829 free(trule->arg.trk_ctr.table.n);
7830 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007831 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007832 * to pass a list of counters to track and allocate them right here using
7833 * stktable_alloc_data_type().
7834 */
7835 }
7836 }
7837
Willy Tarreau620408f2016-10-21 16:37:51 +02007838 /* find the target table for 'tcp-request' layer 5 rules */
7839 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7840 struct proxy *target;
7841
7842 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7843 continue;
7844
7845 if (trule->arg.trk_ctr.table.n)
7846 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7847 else
7848 target = curproxy;
7849
7850 if (!target) {
7851 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7852 curproxy->id, trule->arg.trk_ctr.table.n,
7853 tcp_trk_idx(trule->action));
7854 cfgerr++;
7855 }
7856 else if (target->table.size == 0) {
7857 Alert("Proxy '%s': table '%s' used but not configured.\n",
7858 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7859 cfgerr++;
7860 }
7861 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7862 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7863 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7864 tcp_trk_idx(trule->action));
7865 cfgerr++;
7866 }
7867 else {
7868 free(trule->arg.trk_ctr.table.n);
7869 trule->arg.trk_ctr.table.t = &target->table;
7870 /* Note: if we decide to enhance the track-sc syntax, we may be able
7871 * to pass a list of counters to track and allocate them right here using
7872 * stktable_alloc_data_type().
7873 */
7874 }
7875 }
7876
Willy Tarreaud1f96522010-08-03 19:34:32 +02007877 /* find the target table for 'tcp-request' layer 6 rules */
7878 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7879 struct proxy *target;
7880
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007881 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007882 continue;
7883
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007884 if (trule->arg.trk_ctr.table.n)
7885 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007886 else
7887 target = curproxy;
7888
7889 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007890 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007891 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007892 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007893 cfgerr++;
7894 }
7895 else if (target->table.size == 0) {
7896 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007897 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007898 cfgerr++;
7899 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007900 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007901 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007902 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007903 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007904 cfgerr++;
7905 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007906 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007907 free(trule->arg.trk_ctr.table.n);
7908 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007909 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007910 * to pass a list of counters to track and allocate them right here using
7911 * stktable_alloc_data_type().
7912 */
7913 }
7914 }
7915
Baptiste Assmanne9544932015-11-03 23:31:35 +01007916 /* parse http-request capture rules to ensure id really exists */
7917 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7918 if (hrqrule->action != ACT_CUSTOM ||
7919 hrqrule->action_ptr != http_action_req_capture_by_id)
7920 continue;
7921
7922 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7923 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7924 curproxy->id, hrqrule->arg.capid.idx);
7925 cfgerr++;
7926 }
7927 }
7928
7929 /* parse http-response capture rules to ensure id really exists */
7930 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7931 if (hrqrule->action != ACT_CUSTOM ||
7932 hrqrule->action_ptr != http_action_res_capture_by_id)
7933 continue;
7934
7935 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7936 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7937 curproxy->id, hrqrule->arg.capid.idx);
7938 cfgerr++;
7939 }
7940 }
7941
Willy Tarreau09448f72014-06-25 18:12:15 +02007942 /* find the target table for 'http-request' layer 7 rules */
7943 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7944 struct proxy *target;
7945
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007946 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007947 continue;
7948
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007949 if (hrqrule->arg.trk_ctr.table.n)
7950 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007951 else
7952 target = curproxy;
7953
7954 if (!target) {
7955 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007956 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007957 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007958 cfgerr++;
7959 }
7960 else if (target->table.size == 0) {
7961 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007962 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007963 cfgerr++;
7964 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007965 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007966 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007967 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007968 http_trk_idx(hrqrule->action));
7969 cfgerr++;
7970 }
7971 else {
7972 free(hrqrule->arg.trk_ctr.table.n);
7973 hrqrule->arg.trk_ctr.table.t = &target->table;
7974 /* Note: if we decide to enhance the track-sc syntax, we may be able
7975 * to pass a list of counters to track and allocate them right here using
7976 * stktable_alloc_data_type().
7977 */
7978 }
7979 }
7980
7981 /* find the target table for 'http-response' layer 7 rules */
7982 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7983 struct proxy *target;
7984
7985 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7986 continue;
7987
7988 if (hrqrule->arg.trk_ctr.table.n)
7989 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7990 else
7991 target = curproxy;
7992
7993 if (!target) {
7994 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7995 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7996 http_trk_idx(hrqrule->action));
7997 cfgerr++;
7998 }
7999 else if (target->table.size == 0) {
8000 Alert("Proxy '%s': table '%s' used but not configured.\n",
8001 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8002 cfgerr++;
8003 }
8004 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8005 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8006 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8007 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008008 cfgerr++;
8009 }
8010 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008011 free(hrqrule->arg.trk_ctr.table.n);
8012 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008013 /* Note: if we decide to enhance the track-sc syntax, we may be able
8014 * to pass a list of counters to track and allocate them right here using
8015 * stktable_alloc_data_type().
8016 */
8017 }
8018 }
8019
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008020 /* move any "block" rules at the beginning of the http-request rules */
8021 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8022 /* insert block_rules into http_req_rules at the beginning */
8023 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8024 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8025 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8026 curproxy->http_req_rules.n = curproxy->block_rules.n;
8027 LIST_INIT(&curproxy->block_rules);
8028 }
8029
Emeric Brun32da3c42010-09-23 18:39:19 +02008030 if (curproxy->table.peers.name) {
8031 struct peers *curpeers = peers;
8032
8033 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8034 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8035 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008036 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008037 break;
8038 }
8039 }
8040
8041 if (!curpeers) {
8042 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8043 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008044 free((void *)curproxy->table.peers.name);
8045 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008046 cfgerr++;
8047 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008048 else if (curpeers->state == PR_STSTOPPED) {
8049 /* silently disable this peers section */
8050 curproxy->table.peers.p = NULL;
8051 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008052 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008053 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8054 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008055 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008056 cfgerr++;
8057 }
8058 }
8059
Simon Horman9dc49962015-01-30 11:22:59 +09008060
8061 if (curproxy->email_alert.mailers.name) {
8062 struct mailers *curmailers = mailers;
8063
8064 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8065 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8066 free(curproxy->email_alert.mailers.name);
8067 curproxy->email_alert.mailers.m = curmailers;
8068 curmailers->users++;
8069 break;
8070 }
8071 }
8072
8073 if (!curmailers) {
8074 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8075 curproxy->id, curproxy->email_alert.mailers.name);
8076 free_email_alert(curproxy);
8077 cfgerr++;
8078 }
8079 }
8080
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008081 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008082 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008083 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8084 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8085 "proxy", curproxy->id);
8086 cfgerr++;
8087 goto out_uri_auth_compat;
8088 }
8089
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008090 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008091 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008092 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008093 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008094
Willy Tarreau95fa4692010-02-01 13:05:50 +01008095 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8096 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008097
8098 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008099 uri_auth_compat_req[i++] = "realm";
8100 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8101 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008102
Willy Tarreau95fa4692010-02-01 13:05:50 +01008103 uri_auth_compat_req[i++] = "unless";
8104 uri_auth_compat_req[i++] = "{";
8105 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8106 uri_auth_compat_req[i++] = "}";
8107 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008108
Willy Tarreauff011f22011-01-06 17:51:27 +01008109 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8110 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008111 cfgerr++;
8112 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008113 }
8114
Willy Tarreauff011f22011-01-06 17:51:27 +01008115 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008116
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008117 if (curproxy->uri_auth->auth_realm) {
8118 free(curproxy->uri_auth->auth_realm);
8119 curproxy->uri_auth->auth_realm = NULL;
8120 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008121
8122 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008123 }
8124out_uri_auth_compat:
8125
Dragan Dosen43885c72015-10-01 13:18:13 +02008126 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008127 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008128 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8129 if (!curproxy->conf.logformat_sd_string) {
8130 /* set the default logformat_sd_string */
8131 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8132 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008133 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008134 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008135 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008136
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008137 /* compile the log format */
8138 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008139 if (curproxy->conf.logformat_string != default_http_log_format &&
8140 curproxy->conf.logformat_string != default_tcp_log_format &&
8141 curproxy->conf.logformat_string != clf_http_log_format)
8142 free(curproxy->conf.logformat_string);
8143 curproxy->conf.logformat_string = NULL;
8144 free(curproxy->conf.lfs_file);
8145 curproxy->conf.lfs_file = NULL;
8146 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008147
8148 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8149 free(curproxy->conf.logformat_sd_string);
8150 curproxy->conf.logformat_sd_string = NULL;
8151 free(curproxy->conf.lfsd_file);
8152 curproxy->conf.lfsd_file = NULL;
8153 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008154 }
8155
Willy Tarreau62a61232013-04-12 18:13:46 +02008156 if (curproxy->conf.logformat_string) {
8157 curproxy->conf.args.ctx = ARGC_LOG;
8158 curproxy->conf.args.file = curproxy->conf.lfs_file;
8159 curproxy->conf.args.line = curproxy->conf.lfs_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008160 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008161 if (!parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008162 SMP_VAL_FE_LOG_END, &err)) {
8163 Alert("Parsing [%s:%d]: failed to parse log-format : %s.\n",
8164 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8165 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008166 cfgerr++;
8167 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008168 curproxy->conf.args.file = NULL;
8169 curproxy->conf.args.line = 0;
8170 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008171
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008172 if (curproxy->conf.logformat_sd_string) {
8173 curproxy->conf.args.ctx = ARGC_LOGSD;
8174 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8175 curproxy->conf.args.line = curproxy->conf.lfsd_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008176 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008177 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 +01008178 SMP_VAL_FE_LOG_END, &err)) {
8179 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8180 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8181 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008182 cfgerr++;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008183 } else if (!add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd, &err)) {
8184 Alert("Parsing [%s:%d]: failed to parse log-format-sd : %s.\n",
8185 curproxy->conf.lfs_file, curproxy->conf.lfs_line, err);
8186 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008187 cfgerr++;
8188 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008189 curproxy->conf.args.file = NULL;
8190 curproxy->conf.args.line = 0;
8191 }
8192
Willy Tarreau62a61232013-04-12 18:13:46 +02008193 if (curproxy->conf.uniqueid_format_string) {
8194 curproxy->conf.args.ctx = ARGC_UIF;
8195 curproxy->conf.args.file = curproxy->conf.uif_file;
8196 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIER / OZON.IO8a4e4422016-11-23 00:41:28 +01008197 err = NULL;
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008198 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 +01008199 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR, &err)) {
8200 Alert("Parsing [%s:%d]: failed to parse unique-id : %s.\n",
8201 curproxy->conf.uif_file, curproxy->conf.uif_line, err);
8202 free(err);
Thierry FOURNIER / OZON.IO59fd5112016-11-22 23:50:02 +01008203 cfgerr++;
8204 }
Willy Tarreau62a61232013-04-12 18:13:46 +02008205 curproxy->conf.args.file = NULL;
8206 curproxy->conf.args.line = 0;
8207 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008208
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008209 /* only now we can check if some args remain unresolved.
8210 * This must be done after the users and groups resolution.
8211 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008212 cfgerr += smp_resolve_args(curproxy);
8213 if (!cfgerr)
8214 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008215
Willy Tarreau2738a142006-07-08 17:28:09 +02008216 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008217 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008218 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008219 (!curproxy->timeout.connect ||
8220 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008221 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008222 " | While not properly invalid, you will certainly encounter various problems\n"
8223 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008224 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008225 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008226 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008227 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008228
Willy Tarreau1fa31262007-12-03 00:36:16 +01008229 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8230 * We must still support older configurations, so let's find out whether those
8231 * parameters have been set or must be copied from contimeouts.
8232 */
8233 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008234 if (!curproxy->timeout.tarpit ||
8235 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008236 /* tarpit timeout not set. We search in the following order:
8237 * default.tarpit, curr.connect, default.connect.
8238 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008239 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008240 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008241 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008242 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008243 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008244 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008245 }
8246 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008247 (!curproxy->timeout.queue ||
8248 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008249 /* queue timeout not set. We search in the following order:
8250 * default.queue, curr.connect, default.connect.
8251 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008252 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008253 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008254 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008255 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008256 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008257 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008258 }
8259 }
8260
Willy Tarreau1620ec32011-08-06 17:05:02 +02008261 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008262 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008263 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008264 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008265 }
8266
Willy Tarreau215663d2014-06-13 18:30:23 +02008267 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8268 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8269 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8270 proxy_type_str(curproxy), curproxy->id);
8271 err_code |= ERR_WARN;
8272 }
8273
Willy Tarreau193b8c62012-11-22 00:17:38 +01008274 /* ensure that cookie capture length is not too large */
8275 if (curproxy->capture_len >= global.tune.cookie_len) {
8276 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8277 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8278 err_code |= ERR_WARN;
8279 curproxy->capture_len = global.tune.cookie_len - 1;
8280 }
8281
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008282 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008283 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008284 curproxy->req_cap_pool = create_pool("ptrcap",
8285 curproxy->nb_req_cap * sizeof(char *),
8286 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008287 }
8288
8289 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008290 curproxy->rsp_cap_pool = create_pool("ptrcap",
8291 curproxy->nb_rsp_cap * sizeof(char *),
8292 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008293 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008294
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008295 switch (curproxy->load_server_state_from_file) {
8296 case PR_SRV_STATE_FILE_UNSPEC:
8297 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8298 break;
8299 case PR_SRV_STATE_FILE_GLOBAL:
8300 if (!global.server_state_file) {
8301 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",
8302 curproxy->id);
8303 err_code |= ERR_WARN;
8304 }
8305 break;
8306 }
8307
Willy Tarreaubaaee002006-06-26 02:48:02 +02008308 /* first, we will invert the servers list order */
8309 newsrv = NULL;
8310 while (curproxy->srv) {
8311 struct server *next;
8312
8313 next = curproxy->srv->next;
8314 curproxy->srv->next = newsrv;
8315 newsrv = curproxy->srv;
8316 if (!next)
8317 break;
8318 curproxy->srv = next;
8319 }
8320
Willy Tarreau17edc812014-01-03 12:14:34 +01008321 /* Check that no server name conflicts. This causes trouble in the stats.
8322 * We only emit a warning for the first conflict affecting each server,
8323 * in order to avoid combinatory explosion if all servers have the same
8324 * name. We do that only for servers which do not have an explicit ID,
8325 * because these IDs were made also for distinguishing them and we don't
8326 * want to annoy people who correctly manage them.
8327 */
8328 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8329 struct server *other_srv;
8330
8331 if (newsrv->puid)
8332 continue;
8333
8334 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8335 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8336 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8337 newsrv->conf.file, newsrv->conf.line,
8338 proxy_type_str(curproxy), curproxy->id,
8339 newsrv->id, other_srv->conf.line);
8340 break;
8341 }
8342 }
8343 }
8344
Willy Tarreaudd701652010-05-25 23:03:02 +02008345 /* assign automatic UIDs to servers which don't have one yet */
8346 next_id = 1;
8347 newsrv = curproxy->srv;
8348 while (newsrv != NULL) {
8349 if (!newsrv->puid) {
8350 /* server ID not set, use automatic numbering with first
8351 * spare entry starting with next_svid.
8352 */
8353 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8354 newsrv->conf.id.key = newsrv->puid = next_id;
8355 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8356 }
8357 next_id++;
8358 newsrv = newsrv->next;
8359 }
8360
Willy Tarreau20697042007-11-15 23:26:18 +01008361 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008362 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008363
Willy Tarreau62c3be22012-01-20 13:12:32 +01008364 /*
8365 * If this server supports a maxconn parameter, it needs a dedicated
8366 * tasks to fill the emptied slots when a connection leaves.
8367 * Also, resolve deferred tracking dependency if needed.
8368 */
8369 newsrv = curproxy->srv;
8370 while (newsrv != NULL) {
8371 if (newsrv->minconn > newsrv->maxconn) {
8372 /* Only 'minconn' was specified, or it was higher than or equal
8373 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8374 * this will avoid further useless expensive computations.
8375 */
8376 newsrv->maxconn = newsrv->minconn;
8377 } else if (newsrv->maxconn && !newsrv->minconn) {
8378 /* minconn was not specified, so we set it to maxconn */
8379 newsrv->minconn = newsrv->maxconn;
8380 }
8381
Willy Tarreau17d45382016-12-22 21:16:08 +01008382 /* this will also properly set the transport layer for prod and checks */
8383 if (newsrv->use_ssl || newsrv->check.use_ssl) {
8384 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv)
8385 cfgerr += xprt_get(XPRT_SSL)->prepare_srv(newsrv);
8386 }
Emeric Brun94324a42012-10-11 14:00:19 +02008387
Willy Tarreau2f075e92013-12-03 11:11:34 +01008388 /* set the check type on the server */
8389 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8390
Willy Tarreau62c3be22012-01-20 13:12:32 +01008391 if (newsrv->trackit) {
8392 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008393 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008394 char *pname, *sname;
8395
8396 pname = newsrv->trackit;
8397 sname = strrchr(pname, '/');
8398
8399 if (sname)
8400 *sname++ = '\0';
8401 else {
8402 sname = pname;
8403 pname = NULL;
8404 }
8405
8406 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008407 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008408 if (!px) {
8409 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8410 proxy_type_str(curproxy), curproxy->id,
8411 newsrv->id, pname);
8412 cfgerr++;
8413 goto next_srv;
8414 }
8415 } else
8416 px = curproxy;
8417
8418 srv = findserver(px, sname);
8419 if (!srv) {
8420 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8421 proxy_type_str(curproxy), curproxy->id,
8422 newsrv->id, sname);
8423 cfgerr++;
8424 goto next_srv;
8425 }
8426
Willy Tarreau32091232014-05-16 13:52:00 +02008427 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8428 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8429 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008430 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008431 "tracking as it does not have any check nor agent enabled.\n",
8432 proxy_type_str(curproxy), curproxy->id,
8433 newsrv->id, px->id, srv->id);
8434 cfgerr++;
8435 goto next_srv;
8436 }
8437
8438 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8439
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008440 if (newsrv == srv || loop) {
Willy Tarreau32091232014-05-16 13:52:00 +02008441 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8442 "belongs to a tracking chain looping back to %s/%s.\n",
8443 proxy_type_str(curproxy), curproxy->id,
Frédéric Lécaille2efc6492017-03-14 14:32:17 +01008444 newsrv->id, px->id, srv->id, px->id,
8445 newsrv == srv ? srv->id : loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008446 cfgerr++;
8447 goto next_srv;
8448 }
8449
8450 if (curproxy != px &&
8451 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8452 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8453 "tracking: disable-on-404 option inconsistency.\n",
8454 proxy_type_str(curproxy), curproxy->id,
8455 newsrv->id, px->id, srv->id);
8456 cfgerr++;
8457 goto next_srv;
8458 }
8459
Willy Tarreau62c3be22012-01-20 13:12:32 +01008460 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008461 newsrv->tracknext = srv->trackers;
8462 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008463
8464 free(newsrv->trackit);
8465 newsrv->trackit = NULL;
8466 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008467
8468 /*
8469 * resolve server's resolvers name and update the resolvers pointer
8470 * accordingly
8471 */
8472 if (newsrv->resolvers_id) {
8473 struct dns_resolvers *curr_resolvers;
8474 int found;
8475
8476 found = 0;
8477 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8478 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8479 found = 1;
8480 break;
8481 }
8482 }
8483
8484 if (!found) {
8485 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8486 proxy_type_str(curproxy), curproxy->id,
8487 newsrv->id, newsrv->resolvers_id);
8488 cfgerr++;
8489 } else {
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008490 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 */