blob: 392a692001e4359c0447aa2074d2223ed217d014 [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é2c8d7002014-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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100154 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
156 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
157 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
158 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
159 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100160#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100162#else
163 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100164#endif
165
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100167};
168
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100169/* proxy->options2 */
170static const struct cfg_opt cfg_opts2[] =
171{
172#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
174 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100176#else
177 { "splice-request", 0, 0, 0, 0 },
178 { "splice-response", 0, 0, 0, 0 },
179 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100180#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
182 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
183 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
184 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
185 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
186 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
187 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
189 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400190 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100191 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200192 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200193 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100194 { NULL, 0, 0, 0 }
195};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196
Willy Tarreau6daf3432008-01-22 16:44:08 +0100197static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
199int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100200int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200202/* List head of all known configuration keywords */
203static struct cfg_kw_list cfg_keywords = {
204 .list = LIST_HEAD_INIT(cfg_keywords.list)
205};
206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207/*
208 * converts <str> to a list of listeners which are dynamically allocated.
209 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
210 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
211 * - <port> is a numerical port from 1 to 65535 ;
212 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
213 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200214 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
215 * not NULL, it must be a valid pointer to either NULL or a freeable area that
216 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218int 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 +0200219{
220 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100221 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 int port, end;
223
224 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200225
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100227 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100228 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
230 str = next;
231 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100232 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 *next++ = 0;
234 }
235
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100236 ss2 = str2sa_range(str, &port, &end, err,
237 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
238 if (!ss2)
239 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100242 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port || !end) {
248 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
249 goto fail;
250 }
251
Emeric Bruned760922010-10-22 17:59:25 +0200252 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200253 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
256
257 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100262 else if (ss2->ss_family == AF_UNSPEC) {
263 socklen_t addr_len;
264
265 /* We want to attach to an already bound fd whose number
266 * is in the addr part of ss2 when cast to sockaddr_in.
267 * Note that by definition there is a single listener.
268 * We still have to determine the address family to
269 * register the correct protocol.
270 */
271 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
272 addr_len = sizeof(*ss2);
273 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
274 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
275 goto fail;
276 }
277
278 port = end = get_host_port(ss2);
279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100281 /* OK the address looks correct */
282 ss = *ss2;
283
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 for (; port <= end; port++) {
285 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100286 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200287 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
288 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
289 l->frontend = curproxy;
290 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291
Willy Tarreau40aa0702013-03-10 23:51:38 +0100292 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200294 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100295 l->state = LI_INIT;
296
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100297 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 tcpv4_add_listener(l);
300 }
Emeric Bruned760922010-10-22 17:59:25 +0200301 else if (ss.ss_family == AF_INET6) {
302 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
303 tcpv6_add_listener(l);
304 }
305 else {
Emeric Bruned760922010-10-22 17:59:25 +0200306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200320/* Report a warning if a rule is placed after a 'tcp-request content' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
323int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
324{
325 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
Willy Tarreau61d18892009-03-31 10:49:21 +0200333/* Report a warning if a rule is placed after a 'block' rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200338 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
Willy Tarreau5002f572014-04-23 01:32:02 +0200346/* Report a warning if a rule is placed after an 'http_request' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
349int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
350{
351 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
Willy Tarreau61d18892009-03-31 10:49:21 +0200359/* Report a warning if a rule is placed after a reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
Willy Tarreauee445d92014-04-23 01:39:04 +0200411/* Report a warning if a rule is placed after a 'use-server' rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
414int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
415{
416 if (!LIST_ISEMPTY(&proxy->server_rules)) {
417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200424/* report a warning if a "tcp request connection" rule is dangerously placed */
425int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
426{
427 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
428 warnif_rule_after_block(proxy, file, line, arg) ||
429 warnif_rule_after_http_req(proxy, file, line, arg) ||
430 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
431 warnif_rule_after_reqadd(proxy, file, line, arg) ||
432 warnif_rule_after_redirect(proxy, file, line, arg) ||
433 warnif_rule_after_use_backend(proxy, file, line, arg) ||
434 warnif_rule_after_use_server(proxy, file, line, arg);
435}
436
437/* report a warning if a "tcp request content" rule is dangerously placed */
438int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
439{
440 return warnif_rule_after_block(proxy, file, line, arg) ||
441 warnif_rule_after_http_req(proxy, file, line, arg) ||
442 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
443 warnif_rule_after_reqadd(proxy, file, line, arg) ||
444 warnif_rule_after_redirect(proxy, file, line, arg) ||
445 warnif_rule_after_use_backend(proxy, file, line, arg) ||
446 warnif_rule_after_use_server(proxy, file, line, arg);
447}
448
Willy Tarreau61d18892009-03-31 10:49:21 +0200449/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
Willy Tarreau5002f572014-04-23 01:32:02 +0200452 return warnif_rule_after_http_req(proxy, file, line, arg) ||
453 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
454 warnif_rule_after_reqadd(proxy, file, line, arg) ||
455 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200456 warnif_rule_after_use_backend(proxy, file, line, arg) ||
457 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200458}
459
460/* report a warning if an http-request rule is dangerously placed */
461int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
462{
Willy Tarreau61d18892009-03-31 10:49:21 +0200463 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
464 warnif_rule_after_reqadd(proxy, file, line, arg) ||
465 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200466 warnif_rule_after_use_backend(proxy, file, line, arg) ||
467 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200468}
469
470/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100471int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200472{
473 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
474 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200475 warnif_rule_after_use_backend(proxy, file, line, arg) ||
476 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200477}
478
479/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100480int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200481{
482 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200483 warnif_rule_after_use_backend(proxy, file, line, arg) ||
484 warnif_rule_after_use_server(proxy, file, line, arg);
485}
486
487/* report a warning if a redirect rule is dangerously placed */
488int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
489{
490 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
491 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200492}
493
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100494/* Report it if a request ACL condition uses some keywords that are incompatible
495 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
496 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
497 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100498 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100499static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100500{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100501 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200502 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100503
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100504 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100505 return 0;
506
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100507 acl = acl_cond_conflicts(cond, where);
508 if (acl) {
509 if (acl->name && *acl->name)
510 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
511 file, line, acl->name, sample_ckp_names(where));
512 else
513 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 +0200514 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100515 return ERR_WARN;
516 }
517 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100518 return 0;
519
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100520 if (acl->name && *acl->name)
521 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200522 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100523 else
524 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200525 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100526 return ERR_WARN;
527}
528
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 * parse a line in a <global> section. Returns the error code, 0 if OK, or
531 * any combination of :
532 * - ERR_ABORT: must abort ASAP
533 * - ERR_FATAL: we can continue parsing but not start the service
534 * - ERR_WARN: a warning has been emitted
535 * - ERR_ALERT: an alert has been emitted
536 * Only the two first ones can stop processing, the two others are just
537 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200539int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540{
Willy Tarreau058e9072009-07-20 09:30:05 +0200541 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200542 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543
544 if (!strcmp(args[0], "global")) { /* new section */
545 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200548 else if (!strcmp(args[0], "ca-base")) {
549#ifdef USE_OPENSSL
550 if (global.ca_base != NULL) {
551 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT;
553 goto out;
554 }
555 if (*(args[1]) == 0) {
556 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT | ERR_FATAL;
558 goto out;
559 }
560 global.ca_base = strdup(args[1]);
561#else
562 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
563 err_code |= ERR_ALERT | ERR_FATAL;
564 goto out;
565#endif
566 }
567 else if (!strcmp(args[0], "crt-base")) {
568#ifdef USE_OPENSSL
569 if (global.crt_base != NULL) {
570 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT;
572 goto out;
573 }
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579 global.crt_base = strdup(args[1]);
580#else
581 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584#endif
585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 else if (!strcmp(args[0], "daemon")) {
587 global.mode |= MODE_DAEMON;
588 }
589 else if (!strcmp(args[0], "debug")) {
590 global.mode |= MODE_DEBUG;
591 }
592 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100593 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200595 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100596 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100599 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100601 else if (!strcmp(args[0], "nosplice")) {
602 global.tune.options &= ~GTUNE_USE_SPLICE;
603 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200604 else if (!strcmp(args[0], "nogetaddrinfo")) {
605 global.tune.options &= ~GTUNE_USE_GAI;
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 else if (!strcmp(args[0], "quiet")) {
608 global.mode |= MODE_QUIET;
609 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200610 else if (!strcmp(args[0], "tune.maxpollevents")) {
611 if (global.tune.maxpollevents != 0) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200613 err_code |= ERR_ALERT;
614 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200620 }
621 global.tune.maxpollevents = atol(args[1]);
622 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100623 else if (!strcmp(args[0], "tune.maxaccept")) {
624 if (global.tune.maxaccept != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT;
627 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100633 }
634 global.tune.maxaccept = atol(args[1]);
635 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200636 else if (!strcmp(args[0], "tune.chksize")) {
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.chksize = atol(args[1]);
643 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200644#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200645 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
646 global.tune.sslprivatecache = 1;
647 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100648 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
653 }
654 global.tune.sslcachesize = atol(args[1]);
655 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100656 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
657 unsigned int ssllifetime;
658 const char *res;
659
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
664 }
665
666 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
667 if (res) {
668 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
669 file, linenum, *res, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673
674 global.tune.ssllifetime = ssllifetime;
675 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100676 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.ssl_max_record = atol(args[1]);
683 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200684 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.ssl_default_dh_param = atol(args[1]);
691 if (global.tune.ssl_default_dh_param < 1024) {
692 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200697#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200698 else if (!strcmp(args[0], "tune.bufsize")) {
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.bufsize = atol(args[1]);
705 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
706 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100707 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100708 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200709 }
710 else if (!strcmp(args[0], "tune.maxrewrite")) {
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 global.tune.maxrewrite = atol(args[1]);
717 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
718 global.tune.maxrewrite = global.tune.bufsize / 2;
719 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100720 else if (!strcmp(args[0], "tune.idletimer")) {
721 unsigned int idle;
722 const char *res;
723
724 if (*(args[1]) == 0) {
725 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729
730 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
731 if (res) {
732 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
733 file, linenum, *res, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 if (idle > 65535) {
739 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.idle_timer = idle;
744 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100745 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
746 if (global.tune.client_rcvbuf != 0) {
747 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT;
749 goto out;
750 }
751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.client_rcvbuf = atol(args[1]);
757 }
758 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
759 if (global.tune.server_rcvbuf != 0) {
760 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
761 err_code |= ERR_ALERT;
762 goto out;
763 }
764 if (*(args[1]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 global.tune.server_rcvbuf = atol(args[1]);
770 }
771 else if (!strcmp(args[0], "tune.sndbuf.client")) {
772 if (global.tune.client_sndbuf != 0) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT;
775 goto out;
776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.client_sndbuf = atol(args[1]);
783 }
784 else if (!strcmp(args[0], "tune.sndbuf.server")) {
785 if (global.tune.server_sndbuf != 0) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT;
788 goto out;
789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795 global.tune.server_sndbuf = atol(args[1]);
796 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200797 else if (!strcmp(args[0], "tune.pipesize")) {
798 if (*(args[1]) == 0) {
799 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803 global.tune.pipesize = atol(args[1]);
804 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100805 else if (!strcmp(args[0], "tune.http.cookielen")) {
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811 global.tune.cookie_len = atol(args[1]) + 1;
812 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200813 else if (!strcmp(args[0], "tune.http.maxhdr")) {
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.max_http_hdr = atol(args[1]);
820 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100821 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
822#ifdef USE_ZLIB
823 if (*args[1]) {
824 global.tune.zlibmemlevel = atoi(args[1]);
825 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
826 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
827 file, linenum, args[0]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 } else {
832 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
833 file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837#else
838 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841#endif
842 }
843 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
844#ifdef USE_ZLIB
845 if (*args[1]) {
846 global.tune.zlibwindowsize = atoi(args[1]);
847 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
848 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
849 file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
853 } else {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859#else
860 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863#endif
864 }
William Lallemandf3747832012-11-09 12:33:10 +0100865 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
866 if (*args[1]) {
867 global.tune.comp_maxlevel = atoi(args[1]);
868 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
869 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
870 file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 } else {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881 else if (!strcmp(args[0], "uid")) {
882 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200883 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200884 err_code |= ERR_ALERT;
885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 }
887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 }
892 global.uid = atol(args[1]);
893 }
894 else if (!strcmp(args[0], "gid")) {
895 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200896 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200897 err_code |= ERR_ALERT;
898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899 }
900 if (*(args[1]) == 0) {
901 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905 global.gid = atol(args[1]);
906 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200907 /* user/group name handling */
908 else if (!strcmp(args[0], "user")) {
909 struct passwd *ha_user;
910 if (global.uid != 0) {
911 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
913 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200914 }
915 errno = 0;
916 ha_user = getpwnam(args[1]);
917 if (ha_user != NULL) {
918 global.uid = (int)ha_user->pw_uid;
919 }
920 else {
921 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 +0200922 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200923 }
924 }
925 else if (!strcmp(args[0], "group")) {
926 struct group *ha_group;
927 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200928 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT;
930 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200931 }
932 errno = 0;
933 ha_group = getgrnam(args[1]);
934 if (ha_group != NULL) {
935 global.gid = (int)ha_group->gr_gid;
936 }
937 else {
938 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 +0200939 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200940 }
941 }
942 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
949 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100950 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
951 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
952 file, linenum, args[0], LONGBITS, global.nbproc);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 }
957 else if (!strcmp(args[0], "maxconn")) {
958 if (global.maxconn != 0) {
959 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
968 global.maxconn = atol(args[1]);
969#ifdef SYSTEM_MAXCONN
970 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
971 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);
972 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 }
975#endif /* SYSTEM_MAXCONN */
976 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200977 else if (!strcmp(args[0], "maxsslconn")) {
978#ifdef USE_OPENSSL
979 if (*(args[1]) == 0) {
980 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
983 }
984 global.maxsslconn = atol(args[1]);
985#else
Emeric Brun0914df82012-10-02 18:45:42 +0200986 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200989#endif
990 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100991 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
992#ifdef USE_OPENSSL
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
998 free(global.listen_default_ciphers);
999 global.listen_default_ciphers = strdup(args[1]);
1000#else
1001 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
1004#endif
1005 }
1006 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1007#ifdef USE_OPENSSL
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 free(global.connect_default_ciphers);
1014 global.connect_default_ciphers = strdup(args[1]);
1015#else
1016 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
1019#endif
1020 }
Emeric Brun850efd52014-01-29 12:24:34 +01001021 else if (!strcmp(args[0], "ssl-server-verify")) {
1022 if (*(args[1]) == 0) {
1023 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
1026 }
1027 if (strcmp(args[1],"none") == 0)
1028 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1029 else if (strcmp(args[1],"required") == 0)
1030 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1031 else {
1032 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001037 else if (!strcmp(args[0], "maxconnrate")) {
1038 if (global.cps_lim != 0) {
1039 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1040 err_code |= ERR_ALERT;
1041 goto out;
1042 }
1043 if (*(args[1]) == 0) {
1044 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 global.cps_lim = atol(args[1]);
1049 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001050 else if (!strcmp(args[0], "maxsessrate")) {
1051 if (global.sps_lim != 0) {
1052 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1053 err_code |= ERR_ALERT;
1054 goto out;
1055 }
1056 if (*(args[1]) == 0) {
1057 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060 }
1061 global.sps_lim = atol(args[1]);
1062 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001063 else if (!strcmp(args[0], "maxsslrate")) {
1064 if (global.ssl_lim != 0) {
1065 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT;
1067 goto out;
1068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074 global.ssl_lim = atol(args[1]);
1075 }
William Lallemandd85f9172012-11-09 17:05:39 +01001076 else if (!strcmp(args[0], "maxcomprate")) {
1077 if (*(args[1]) == 0) {
1078 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
1081 }
1082 global.comp_rate_lim = atoi(args[1]) * 1024;
1083 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001084 else if (!strcmp(args[0], "maxpipes")) {
1085 if (global.maxpipes != 0) {
1086 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001087 err_code |= ERR_ALERT;
1088 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001089 }
1090 if (*(args[1]) == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001094 }
1095 global.maxpipes = atol(args[1]);
1096 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001097 else if (!strcmp(args[0], "maxzlibmem")) {
1098 if (*(args[1]) == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto out;
1102 }
William Lallemande3a7d992012-11-20 11:25:20 +01001103 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001104 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001105 else if (!strcmp(args[0], "maxcompcpuusage")) {
1106 if (*(args[1]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
1110 }
1111 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001112 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001113 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117}
1118
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 else if (!strcmp(args[0], "ulimit-n")) {
1120 if (global.rlimit_nofile != 0) {
1121 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT;
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 }
1125 if (*(args[1]) == 0) {
1126 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 }
1130 global.rlimit_nofile = atol(args[1]);
1131 }
1132 else if (!strcmp(args[0], "chroot")) {
1133 if (global.chroot != NULL) {
1134 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138 if (*(args[1]) == 0) {
1139 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001142 }
1143 global.chroot = strdup(args[1]);
1144 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001145 else if (!strcmp(args[0], "description")) {
1146 int i, len=0;
1147 char *d;
1148
1149 if (!*args[1]) {
1150 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1151 file, linenum, args[0]);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
1154 }
1155
Willy Tarreau348acfe2014-04-14 15:00:39 +02001156 for (i = 1; *args[i]; i++)
1157 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001158
1159 if (global.desc)
1160 free(global.desc);
1161
1162 global.desc = d = (char *)calloc(1, len);
1163
Willy Tarreau348acfe2014-04-14 15:00:39 +02001164 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1165 for (i = 2; *args[i]; i++)
1166 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001167 }
1168 else if (!strcmp(args[0], "node")) {
1169 int i;
1170 char c;
1171
1172 for (i=0; args[1][i]; i++) {
1173 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001174 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1175 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001176 break;
1177 }
1178
1179 if (!i || args[1][i]) {
1180 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1181 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1182 file, linenum, args[0]);
1183 err_code |= ERR_ALERT | ERR_FATAL;
1184 goto out;
1185 }
1186
1187 if (global.node)
1188 free(global.node);
1189
1190 global.node = strdup(args[1]);
1191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192 else if (!strcmp(args[0], "pidfile")) {
1193 if (global.pidfile != NULL) {
1194 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001195 err_code |= ERR_ALERT;
1196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 }
1198 if (*(args[1]) == 0) {
1199 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202 }
1203 global.pidfile = strdup(args[1]);
1204 }
Emeric Bruned760922010-10-22 17:59:25 +02001205 else if (!strcmp(args[0], "unix-bind")) {
1206 int cur_arg = 1;
1207 while (*(args[cur_arg])) {
1208 if (!strcmp(args[cur_arg], "prefix")) {
1209 if (global.unix_bind.prefix != NULL) {
1210 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1211 err_code |= ERR_ALERT;
1212 cur_arg += 2;
1213 continue;
1214 }
1215
1216 if (*(args[cur_arg+1]) == 0) {
1217 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1222 cur_arg += 2;
1223 continue;
1224 }
1225
1226 if (!strcmp(args[cur_arg], "mode")) {
1227
1228 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1229 cur_arg += 2;
1230 continue;
1231 }
1232
1233 if (!strcmp(args[cur_arg], "uid")) {
1234
1235 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1236 cur_arg += 2;
1237 continue;
1238 }
1239
1240 if (!strcmp(args[cur_arg], "gid")) {
1241
1242 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1243 cur_arg += 2;
1244 continue;
1245 }
1246
1247 if (!strcmp(args[cur_arg], "user")) {
1248 struct passwd *user;
1249
1250 user = getpwnam(args[cur_arg + 1]);
1251 if (!user) {
1252 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1253 file, linenum, args[0], args[cur_arg + 1 ]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257
1258 global.unix_bind.ux.uid = user->pw_uid;
1259 cur_arg += 2;
1260 continue;
1261 }
1262
1263 if (!strcmp(args[cur_arg], "group")) {
1264 struct group *group;
1265
1266 group = getgrnam(args[cur_arg + 1]);
1267 if (!group) {
1268 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1269 file, linenum, args[0], args[cur_arg + 1 ]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272 }
1273
1274 global.unix_bind.ux.gid = group->gr_gid;
1275 cur_arg += 2;
1276 continue;
1277 }
1278
Willy Tarreaub48f9582011-09-05 01:17:06 +02001279 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001280 file, linenum, args[0]);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284 }
William Lallemand0f99e342011-10-12 17:50:54 +02001285 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1286 /* delete previous herited or defined syslog servers */
1287 struct logsrv *back;
1288 struct logsrv *tmp;
1289
1290 if (*(args[1]) != 0) {
1291 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
1295
1296 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1297 LIST_DEL(&tmp->list);
1298 free(tmp);
1299 }
1300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001302 struct sockaddr_storage *sk;
1303 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001304 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001305 int arg = 0;
1306 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 if (*(args[1]) == 0 || *(args[2]) == 0) {
1309 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 }
William Lallemand0f99e342011-10-12 17:50:54 +02001313
1314 logsrv = calloc(1, sizeof(struct logsrv));
1315
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001316 /* just after the address, a length may be specified */
1317 if (strcmp(args[arg+2], "len") == 0) {
1318 len = atoi(args[arg+3]);
1319 if (len < 80 || len > 65535) {
1320 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1321 file, linenum, args[arg+3]);
1322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
1324 }
1325 logsrv->maxlen = len;
1326
1327 /* skip these two args */
1328 arg += 2;
1329 }
1330 else
1331 logsrv->maxlen = MAX_SYSLOG_LEN;
1332
1333 if (logsrv->maxlen > global.max_syslog_len) {
1334 global.max_syslog_len = logsrv->maxlen;
1335 logline = realloc(logline, global.max_syslog_len + 1);
1336 }
1337
1338 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001339 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001340 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001342 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
1344
William Lallemand0f99e342011-10-12 17:50:54 +02001345 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001346 if (*(args[arg+3])) {
1347 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001348 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001349 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001350 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001351 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 }
1353 }
1354
William Lallemand0f99e342011-10-12 17:50:54 +02001355 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001356 if (*(args[arg+4])) {
1357 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001358 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001359 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001361 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001362 }
1363 }
1364
Willy Tarreau902636f2013-03-10 19:44:48 +01001365 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001366 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001367 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001368 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001369 free(logsrv);
1370 goto out;
1371 }
1372 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001373
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001374 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001375 if (port1 != port2) {
1376 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1377 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001378 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001379 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001380 goto out;
1381 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001382
William Lallemand0f99e342011-10-12 17:50:54 +02001383 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001384 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001385 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387
William Lallemand0f99e342011-10-12 17:50:54 +02001388 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001389 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001390 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1391 char *name;
1392 int len;
1393
1394 if (global.log_send_hostname != NULL) {
1395 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1396 err_code |= ERR_ALERT;
1397 goto out;
1398 }
1399
1400 if (*(args[1]))
1401 name = args[1];
1402 else
1403 name = hostname;
1404
1405 len = strlen(name);
1406
1407 /* We'll add a space after the name to respect the log format */
1408 free(global.log_send_hostname);
1409 global.log_send_hostname = malloc(len + 2);
1410 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1411 }
Kevinm48936af2010-12-22 16:08:21 +00001412 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1413 if (*(args[1]) == 0) {
1414 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto out;
1417 }
1418 free(global.log_tag);
1419 global.log_tag = strdup(args[1]);
1420 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001421 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1422 if (global.spread_checks != 0) {
1423 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001424 err_code |= ERR_ALERT;
1425 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001426 }
1427 if (*(args[1]) == 0) {
1428 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001431 }
1432 global.spread_checks = atol(args[1]);
1433 if (global.spread_checks < 0 || global.spread_checks > 50) {
1434 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001435 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001438 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1439 const char *err;
1440 unsigned int val;
1441
1442
1443 if (*(args[1]) == 0) {
1444 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
1448
1449 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1450 if (err) {
1451 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1452 err_code |= ERR_ALERT | ERR_FATAL;
1453 }
1454 global.max_spread_checks = val;
1455 if (global.max_spread_checks < 0) {
1456 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1457 err_code |= ERR_ALERT | ERR_FATAL;
1458 }
1459 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001460 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1461#ifdef USE_CPU_AFFINITY
1462 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001463 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001464 unsigned long cpus = 0;
1465
1466 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001467 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001468 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001469 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001470 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001471 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001472 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001473 proc = atol(args[1]);
1474 if (proc >= 1 && proc <= LONGBITS)
1475 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001476 }
1477
1478 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001479 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",
1480 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
1483 }
1484
1485 cur_arg = 2;
1486 while (*args[cur_arg]) {
1487 unsigned int low, high;
1488
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001489 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001490 char *dash = strchr(args[cur_arg], '-');
1491
1492 low = high = str2uic(args[cur_arg]);
1493 if (dash)
1494 high = str2uic(dash + 1);
1495
1496 if (high < low) {
1497 unsigned int swap = low;
1498 low = high;
1499 high = swap;
1500 }
1501
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001502 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001503 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001504 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001505 err_code |= ERR_ALERT | ERR_FATAL;
1506 goto out;
1507 }
1508
1509 while (low <= high)
1510 cpus |= 1UL << low++;
1511 }
1512 else {
1513 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1514 file, linenum, args[0], args[cur_arg]);
1515 err_code |= ERR_ALERT | ERR_FATAL;
1516 goto out;
1517 }
1518 cur_arg++;
1519 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001520 for (i = 0; i < LONGBITS; i++)
1521 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001522 global.cpu_map[i] = cpus;
1523#else
1524 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1525 err_code |= ERR_ALERT | ERR_FATAL;
1526 goto out;
1527#endif
1528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001530 struct cfg_kw_list *kwl;
1531 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001532 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001533
1534 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1535 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1536 if (kwl->kw[index].section != CFG_GLOBAL)
1537 continue;
1538 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001539 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001540 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001541 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001542 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001543 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001544 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001545 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001546 err_code |= ERR_WARN;
1547 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001548 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001549 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001550 }
1551 }
1552 }
1553
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001555 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001557
Willy Tarreau058e9072009-07-20 09:30:05 +02001558 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001559 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001560 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561}
1562
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001563void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001565 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 defproxy.mode = PR_MODE_TCP;
1567 defproxy.state = PR_STNEW;
1568 defproxy.maxconn = cfg_maxpconn;
1569 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001570
Simon Horman66183002013-02-23 10:16:43 +09001571 defproxy.defsrv.check.inter = DEF_CHKINTR;
1572 defproxy.defsrv.check.fastinter = 0;
1573 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001574 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1575 defproxy.defsrv.agent.fastinter = 0;
1576 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001577 defproxy.defsrv.check.rise = DEF_RISETIME;
1578 defproxy.defsrv.check.fall = DEF_FALLTIME;
1579 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1580 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001581 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001582 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001583 defproxy.defsrv.maxqueue = 0;
1584 defproxy.defsrv.minconn = 0;
1585 defproxy.defsrv.maxconn = 0;
1586 defproxy.defsrv.slowstart = 0;
1587 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1588 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1589 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590}
1591
Willy Tarreauade5ec42010-01-28 19:33:49 +01001592
Willy Tarreau63af98d2014-05-18 08:11:41 +02001593/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1594 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1595 * ERR_FATAL in case of error.
1596 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001597static int create_cond_regex_rule(const char *file, int line,
1598 struct proxy *px, int dir, int action, int flags,
1599 const char *cmd, const char *reg, const char *repl,
1600 const char **cond_start)
1601{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001602 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001603 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001604 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001605 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001606 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001607 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001608 int cs;
1609 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001610
1611 if (px == &defproxy) {
1612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001613 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614 goto err;
1615 }
1616
1617 if (*reg == 0) {
1618 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001619 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001620 goto err;
1621 }
1622
1623 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001624 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001625
Willy Tarreau5321c422010-01-28 20:35:13 +01001626 if (cond_start &&
1627 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001628 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1629 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1630 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001631 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001632 goto err;
1633 }
1634 }
1635 else if (cond_start && **cond_start) {
1636 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1637 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001638 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001639 goto err;
1640 }
1641
Willy Tarreau63af98d2014-05-18 08:11:41 +02001642 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001643 (dir == SMP_OPT_DIR_REQ) ?
1644 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1645 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1646 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001647
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001648 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001649 if (!preg) {
1650 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001651 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001652 goto err;
1653 }
1654
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001655 cs = !(flags & REG_ICASE);
1656 cap = !(flags & REG_NOSUB);
1657 error = NULL;
1658 if (!regex_comp(reg, preg, cs, cap, &error)) {
1659 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1660 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001661 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001662 goto err;
1663 }
1664
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001665 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001666 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001667 if (repl && err) {
1668 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1669 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001670 ret_code |= ERR_ALERT | ERR_FATAL;
1671 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001672 }
1673
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001674 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001675 ret_code |= ERR_WARN;
1676
1677 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001678
Willy Tarreau63af98d2014-05-18 08:11:41 +02001679 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001680 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001681 err:
1682 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 free(errmsg);
1684 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001685}
1686
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001688 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001689 * Returns the error code, 0 if OK, or any combination of :
1690 * - ERR_ABORT: must abort ASAP
1691 * - ERR_FATAL: we can continue parsing but not start the service
1692 * - ERR_WARN: a warning has been emitted
1693 * - ERR_ALERT: an alert has been emitted
1694 * Only the two first ones can stop processing, the two others are just
1695 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001697int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1698{
1699 static struct peers *curpeers = NULL;
1700 struct peer *newpeer = NULL;
1701 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001702 struct bind_conf *bind_conf;
1703 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001704 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001705 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001706
1707 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001708 if (!*args[1]) {
1709 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001710 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001711 goto out;
1712 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001713
1714 err = invalid_char(args[1]);
1715 if (err) {
1716 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1717 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001718 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001719 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001720 }
1721
1722 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1723 /*
1724 * If there are two proxies with the same name only following
1725 * combinations are allowed:
1726 */
1727 if (strcmp(curpeers->id, args[1]) == 0) {
1728 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1729 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1730 err_code |= ERR_WARN;
1731 }
1732 }
1733
1734 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1735 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1736 err_code |= ERR_ALERT | ERR_ABORT;
1737 goto out;
1738 }
1739
1740 curpeers->next = peers;
1741 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001742 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001743 curpeers->conf.line = linenum;
1744 curpeers->last_change = now.tv_sec;
1745 curpeers->id = strdup(args[1]);
1746 }
1747 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001748 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001749 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001750 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001751
1752 if (!*args[2]) {
1753 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1754 file, linenum, args[0]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758
1759 err = invalid_char(args[1]);
1760 if (err) {
1761 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1762 file, linenum, *err, args[1]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
1765 }
1766
1767 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1768 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1769 err_code |= ERR_ALERT | ERR_ABORT;
1770 goto out;
1771 }
1772
1773 /* the peers are linked backwards first */
1774 curpeers->count++;
1775 newpeer->next = curpeers->remote;
1776 curpeers->remote = newpeer;
1777 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001778 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001779 newpeer->conf.line = linenum;
1780
1781 newpeer->last_change = now.tv_sec;
1782 newpeer->id = strdup(args[1]);
1783
Willy Tarreau902636f2013-03-10 19:44:48 +01001784 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001785 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001786 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001787 err_code |= ERR_ALERT | ERR_FATAL;
1788 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001789 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001790
1791 proto = protocol_by_family(sk->ss_family);
1792 if (!proto || !proto->connect) {
1793 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1794 file, linenum, args[0], args[1]);
1795 err_code |= ERR_ALERT | ERR_FATAL;
1796 goto out;
1797 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001798
1799 if (port1 != port2) {
1800 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1801 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804 }
1805
Willy Tarreau2aa38802013-02-20 19:20:59 +01001806 if (!port1) {
1807 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1808 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001812
Emeric Brun32da3c42010-09-23 18:39:19 +02001813 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001814 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001815 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001816 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001817
Emeric Brun32da3c42010-09-23 18:39:19 +02001818 if (strcmp(newpeer->id, localpeer) == 0) {
1819 /* Current is local peer, it define a frontend */
1820 newpeer->local = 1;
1821
1822 if (!curpeers->peers_fe) {
1823 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1824 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1825 err_code |= ERR_ALERT | ERR_ABORT;
1826 goto out;
1827 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001828
Willy Tarreau237250c2011-07-29 01:49:03 +02001829 init_new_proxy(curpeers->peers_fe);
1830 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001831
1832 curpeers->peers_fe->last_change = now.tv_sec;
1833 curpeers->peers_fe->id = strdup(args[1]);
1834 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001835 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001836 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1837 curpeers->peers_fe->timeout.connect = 5000;
1838 curpeers->peers_fe->accept = peer_accept;
1839 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001840 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1841 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001842
1843 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1844
Willy Tarreau902636f2013-03-10 19:44:48 +01001845 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1846 if (errmsg && *errmsg) {
1847 indent_msg(&errmsg, 2);
1848 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau